Skip to content

Commit f7b0be9

Browse files
authored
fix: core db crash (#215)
* fix: core db crash * fix: exception * fix: PR comments * fix: update test * fix: update test * fix: update test * fix: version * fix: rename * fix: pr comments * fix: pr comments * fix: pr comments * fix: update tests
1 parent 5df213a commit f7b0be9

File tree

10 files changed

+803
-159
lines changed

10 files changed

+803
-159
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## [Unreleased]
99

10+
## [7.0.1] - 2024-04-17
11+
12+
- Fixes issues with partial failures during tenant creation
13+
1014
## [7.0.0] - 2024-03-13
1115

1216
- Replace `TotpNotEnabledError` with `UnknownUserIdTotpError`.

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ plugins {
22
id 'java-library'
33
}
44

5-
version = "7.0.0"
5+
version = "7.0.1"
66

77
repositories {
88
mavenCentral()

pluginInterfaceSupported.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"_comment": "contains a list of plugin interfaces branch names that this core supports",
33
"versions": [
4-
"6.0"
4+
"6.1"
55
]
66
}

src/main/java/io/supertokens/storage/postgresql/ConnectionPool.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.zaxxer.hikari.HikariConfig;
2121
import com.zaxxer.hikari.HikariDataSource;
2222
import io.supertokens.pluginInterface.exceptions.DbInitException;
23+
import io.supertokens.pluginInterface.exceptions.StorageQueryException;
2324
import io.supertokens.storage.postgresql.config.Config;
2425
import io.supertokens.storage.postgresql.config.PostgreSQLConfig;
2526
import io.supertokens.storage.postgresql.output.Logging;
@@ -35,12 +36,14 @@ public class ConnectionPool extends ResourceDistributor.SingletonResource {
3536
private static final String RESOURCE_KEY = "io.supertokens.storage.postgresql.ConnectionPool";
3637
private HikariDataSource hikariDataSource;
3738
private final Start start;
39+
private PostConnectCallback postConnectCallback;
3840

39-
private ConnectionPool(Start start) {
41+
private ConnectionPool(Start start, PostConnectCallback postConnectCallback) {
4042
this.start = start;
43+
this.postConnectCallback = postConnectCallback;
4144
}
4245

43-
private synchronized void initialiseHikariDataSource() throws SQLException {
46+
private synchronized void initialiseHikariDataSource() throws SQLException, StorageQueryException {
4447
if (this.hikariDataSource != null) {
4548
return;
4649
}
@@ -99,6 +102,19 @@ private synchronized void initialiseHikariDataSource() throws SQLException {
99102
} catch (Exception e) {
100103
throw new SQLException(e);
101104
}
105+
106+
try {
107+
try (Connection con = hikariDataSource.getConnection()) {
108+
this.postConnectCallback.apply(con);
109+
}
110+
} catch (StorageQueryException e) {
111+
// if an exception happens here, we want to set the hikariDataSource to null once again so that
112+
// whenever the getConnection is called again, we want to re-attempt creation of tables and tenant
113+
// entries for this storage
114+
hikariDataSource.close();
115+
hikariDataSource = null;
116+
throw e;
117+
}
102118
}
103119

104120
private static int getTimeToWaitToInit(Start start) {
@@ -133,7 +149,7 @@ static boolean isAlreadyInitialised(Start start) {
133149
return getInstance(start) != null && getInstance(start).hikariDataSource != null;
134150
}
135151

136-
static void initPool(Start start, boolean shouldWait) throws DbInitException {
152+
static void initPool(Start start, boolean shouldWait, PostConnectCallback postConnectCallback) throws DbInitException {
137153
if (isAlreadyInitialised(start)) {
138154
return;
139155
}
@@ -146,7 +162,7 @@ static void initPool(Start start, boolean shouldWait) throws DbInitException {
146162
" specified the correct values for ('postgresql_host' and 'postgresql_port') or for "
147163
+ "'postgresql_connection_uri'";
148164
try {
149-
ConnectionPool con = new ConnectionPool(start);
165+
ConnectionPool con = new ConnectionPool(start, postConnectCallback);
150166
start.getResourceDistributor().setResource(RESOURCE_KEY, con);
151167
while (true) {
152168
try {
@@ -189,7 +205,7 @@ static void initPool(Start start, boolean shouldWait) throws DbInitException {
189205
}
190206
}
191207

192-
public static Connection getConnection(Start start) throws SQLException {
208+
public static Connection getConnection(Start start) throws SQLException, StorageQueryException {
193209
if (getInstance(start) == null) {
194210
throw new IllegalStateException("Please call initPool before getConnection");
195211
}
@@ -216,4 +232,9 @@ static void close(Start start) {
216232
}
217233
}
218234
}
235+
236+
@FunctionalInterface
237+
public static interface PostConnectCallback {
238+
void apply(Connection connection) throws StorageQueryException;
239+
}
219240
}

src/main/java/io/supertokens/storage/postgresql/Start.java

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,7 @@
9898
import java.sql.Connection;
9999
import java.sql.SQLException;
100100
import java.sql.SQLTransactionRollbackException;
101-
import java.util.ArrayList;
102-
import java.util.HashMap;
103-
import java.util.List;
104-
import java.util.Set;
101+
import java.util.*;
105102

106103
import static io.supertokens.storage.postgresql.QueryExecutorTemplate.execute;
107104

@@ -218,7 +215,7 @@ public void stopLogging() {
218215
}
219216

220217
@Override
221-
public void initStorage(boolean shouldWait) throws DbInitException {
218+
public void initStorage(boolean shouldWait, List<TenantIdentifier> tenantIdentifiers) throws DbInitException {
222219
if (ConnectionPool.isAlreadyInitialised(this)) {
223220
return;
224221
}
@@ -228,8 +225,20 @@ public void initStorage(boolean shouldWait) throws DbInitException {
228225
mainThread = Thread.currentThread();
229226
}
230227
try {
231-
ConnectionPool.initPool(this, shouldWait);
232-
GeneralQueries.createTablesIfNotExists(this);
228+
ConnectionPool.initPool(this, shouldWait, (con) -> {
229+
try {
230+
GeneralQueries.createTablesIfNotExists(this, con);
231+
} catch (SQLException e) {
232+
throw new StorageQueryException(e);
233+
}
234+
for (TenantIdentifier tenantIdentifier : tenantIdentifiers) {
235+
try {
236+
this.addTenantIdInTargetStorage_Transaction(con, tenantIdentifier);
237+
} catch (DuplicateTenantException e) {
238+
// ignore
239+
}
240+
}
241+
});
233242
} catch (Exception e) {
234243
throw new DbInitException(e);
235244
}
@@ -465,7 +474,7 @@ public void deleteAllInformation() throws StorageQueryException {
465474
}
466475
ProcessState.getInstance(this).clear();
467476
try {
468-
initStorage(false);
477+
initStorage(false, new ArrayList<>());
469478
enabled = true; // Allow get connection to work, to delete the data
470479
GeneralQueries.deleteAllTables(this);
471480

@@ -2283,6 +2292,22 @@ public void addTenantIdInTargetStorage(TenantIdentifier tenantIdentifier)
22832292
}
22842293
}
22852294

2295+
public void addTenantIdInTargetStorage_Transaction(Connection con, TenantIdentifier tenantIdentifier)
2296+
throws DuplicateTenantException, StorageQueryException {
2297+
try {
2298+
MultitenancyQueries.addTenantIdInTargetStorage_Transaction(this, con, tenantIdentifier);
2299+
} catch (SQLException e) {
2300+
if (e instanceof PSQLException) {
2301+
PostgreSQLConfig config = Config.getConfig(this);
2302+
if (isPrimaryKeyError(((PSQLException) e).getServerErrorMessage(),
2303+
config.getTenantsTable())) {
2304+
throw new DuplicateTenantException();
2305+
}
2306+
}
2307+
throw new StorageQueryException(e);
2308+
}
2309+
}
2310+
22862311
@Override
22872312
public void overwriteTenantConfig(TenantConfig tenantConfig)
22882313
throws TenantOrAppNotFoundException, StorageQueryException, DuplicateThirdPartyIdException,

0 commit comments

Comments
 (0)