diff --git a/CHANGELOG.md b/CHANGELOG.md index d3fd7016f..3fd7c7f21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [8.0.3] - 2024-04-22 + +- Fixes issue with core startup when creation of CUD/app/tenant has partial failure + ## [8.0.2] - 2024-03-21 - Fixes userIdMapping queries diff --git a/build.gradle b/build.gradle index 8300e7dd1..1dacbbb32 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ compileTestJava { options.encoding = "UTF-8" } // } //} -version = "8.0.2" +version = "8.0.3" repositories { diff --git a/pluginInterfaceSupported.json b/pluginInterfaceSupported.json index e9d4c148c..90dfc0cab 100644 --- a/pluginInterfaceSupported.json +++ b/pluginInterfaceSupported.json @@ -1,6 +1,6 @@ { "_comment": "contains a list of plugin interfaces branch names that this core supports", "versions": [ - "5.0" + "5.1" ] } \ No newline at end of file diff --git a/src/main/java/io/supertokens/Main.java b/src/main/java/io/supertokens/Main.java index 3620b2bf8..00f944742 100644 --- a/src/main/java/io/supertokens/Main.java +++ b/src/main/java/io/supertokens/Main.java @@ -187,7 +187,7 @@ private void init() throws IOException, StorageQueryException { } } try { - StorageLayer.getBaseStorage(this).initStorage(true); + StorageLayer.getBaseStorage(this).initStorage(true, List.of()); } catch (DbInitException e) { throw new QuitProgramException(e); } @@ -208,6 +208,12 @@ private void init() throws IOException, StorageQueryException { // load all configs for each of the tenants. MultitenancyHelper.getInstance(this).loadConfig(new ArrayList<>()); + if (!StorageLayer.isInMemDb(this)) { + // we want to init storage connection once again so that the base storage also contains the right + // tenant identifier set passed to the init. So we call the resetPostConnectCallbackForBaseTenantStorage. + StorageLayer.getBaseStorage(this).close(); + } + // init storage layers for each unique db connection based on unique (user pool ID, connection pool ID). MultitenancyHelper.getInstance(this).loadStorageLayer(); } catch (InvalidConfigException e) { diff --git a/src/main/java/io/supertokens/inmemorydb/Start.java b/src/main/java/io/supertokens/inmemorydb/Start.java index 4ba263eff..7b95c4308 100644 --- a/src/main/java/io/supertokens/inmemorydb/Start.java +++ b/src/main/java/io/supertokens/inmemorydb/Start.java @@ -175,7 +175,7 @@ public void stopLogging() { } @Override - public void initStorage(boolean shouldWait) throws DbInitException { + public void initStorage(boolean shouldWait, List tenantIdentifiers) throws DbInitException { if (ConnectionPool.isAlreadyInitialised(this)) { return; } diff --git a/src/main/java/io/supertokens/storageLayer/StorageLayer.java b/src/main/java/io/supertokens/storageLayer/StorageLayer.java index 5145e7c1c..e87e114d0 100644 --- a/src/main/java/io/supertokens/storageLayer/StorageLayer.java +++ b/src/main/java/io/supertokens/storageLayer/StorageLayer.java @@ -279,9 +279,25 @@ public static void loadAllTenantStorage(Main main, TenantConfig[] tenants) Map resources = main.getResourceDistributor() .getAllResourcesWithResourceKey(RESOURCE_KEY); - for (ResourceDistributor.SingletonResource resource : resources.values()) { + + // we are creating this map to find tenantIdentifiers that are associated with each storage. + // when we call the initStorage, the storage instance remembers the tenants that need to be created + // in case error happens. Whenever the connection is restored, the tenant entries are created on that + // storage. If the storage is already live, then it will be a no-op. + Map> storageToTenantIdentifiersMap = new HashMap<>(); + // Set tenant identifiers handled by each storage instance before initialising them + for (ResourceDistributor.KeyClass key : resources.keySet()) { + if (storageToTenantIdentifiersMap.get(((StorageLayer) resources.get(key)).storage) == null) { + storageToTenantIdentifiersMap.put(((StorageLayer) resources.get(key)).storage, new HashSet<>()); + } + storageToTenantIdentifiersMap.get(((StorageLayer) resources.get(key)).storage).add(key.getTenantIdentifier()); + } + + for (ResourceDistributor.KeyClass key : resources.keySet()) { + ResourceDistributor.SingletonResource resource = resources.get(key); + try { - ((StorageLayer) resource).storage.initStorage(false); + ((StorageLayer) resource).storage.initStorage(false, new ArrayList<>(storageToTenantIdentifiersMap.get(((StorageLayer) resource).storage))); ((StorageLayer) resource).storage.initFileLogging( Config.getBaseConfig(main).getInfoLogPath(main), Config.getBaseConfig(main).getErrorLogPath(main)); diff --git a/src/test/java/io/supertokens/test/multitenant/LogTest.java b/src/test/java/io/supertokens/test/multitenant/LogTest.java index 80425ce51..6296ea06c 100644 --- a/src/test/java/io/supertokens/test/multitenant/LogTest.java +++ b/src/test/java/io/supertokens/test/multitenant/LogTest.java @@ -148,7 +148,7 @@ public void testLogThatEachLineIsUniqueOnStartup() throws Exception { uniqueLines.add(line); } - assertEquals(uniqueLines.size(), lines.length); + assertEquals(uniqueLines.size(), lines.length - 1); // we have 1 repeating line which initialises connection pool assertEquals(7, Multitenancy.getAllTenants(process.getProcess()).length);