19
19
20
20
import com .zaxxer .hikari .HikariConfig ;
21
21
import com .zaxxer .hikari .HikariDataSource ;
22
- import io .supertokens .pluginInterface .exceptions .QuitProgramFromPluginException ;
22
+ import io .supertokens .pluginInterface .exceptions .DbInitException ;
23
23
import io .supertokens .storage .postgresql .config .Config ;
24
24
import io .supertokens .storage .postgresql .config .PostgreSQLConfig ;
25
25
import io .supertokens .storage .postgresql .output .Logging ;
33
33
public class ConnectionPool extends ResourceDistributor .SingletonResource {
34
34
35
35
private static final String RESOURCE_KEY = "io.supertokens.storage.postgresql.ConnectionPool" ;
36
- private static HikariDataSource hikariDataSource = null ;
36
+ private HikariDataSource hikariDataSource ;
37
+ private final Start start ;
37
38
38
39
private ConnectionPool (Start start ) {
39
- if (!start .enabled ) {
40
- throw new RuntimeException ("Connection to refused" ); // emulates exception thrown by Hikari
41
- }
42
-
43
- if (ConnectionPool .hikariDataSource != null ) {
44
- // This implies that it was already created before and that
45
- // there is no need to create Hikari again.
40
+ this .start = start ;
41
+ }
46
42
47
- // If ConnectionPool.hikariDataSource == null, it implies that
48
- // either the config file had changed somehow (which means the plugin JAR was reloaded, resulting in static
49
- // variables to be set to null), or it means that this is the first time we are trying to connect to a db
50
- // (applicable only for testing).
43
+ private synchronized void initialiseHikariDataSource () throws SQLException {
44
+ if (this .hikariDataSource != null ) {
51
45
return ;
52
46
}
47
+ if (!start .enabled ) {
48
+ throw new RuntimeException ("Connection to refused" ); // emulates exception thrown by Hikari
49
+ }
53
50
54
51
HikariConfig config = new HikariConfig ();
55
52
PostgreSQLConfig userConfig = Config .getConfig (start );
@@ -92,8 +89,12 @@ private ConnectionPool(Start start) {
92
89
// SuperTokens
93
90
// - Failed to validate connection org.mariadb.jdbc.MariaDbConnection@79af83ae (Connection.setNetworkTimeout
94
91
// cannot be called on a closed connection). Possibly consider using a shorter maxLifetime value.
95
- config .setPoolName ("SuperTokens" );
96
- hikariDataSource = new HikariDataSource (config );
92
+ config .setPoolName (start .getUserPoolId () + "~" + start .getConnectionPoolId ());
93
+ try {
94
+ hikariDataSource = new HikariDataSource (config );
95
+ } catch (Exception e ) {
96
+ throw new SQLException (e );
97
+ }
97
98
}
98
99
99
100
private static int getTimeToWaitToInit (Start start ) {
@@ -120,30 +121,41 @@ private static ConnectionPool getInstance(Start start) {
120
121
return (ConnectionPool ) start .getResourceDistributor ().getResource (RESOURCE_KEY );
121
122
}
122
123
123
- static void initPool (Start start ) {
124
- if (getInstance (start ) != null ) {
124
+ static boolean isAlreadyInitialised (Start start ) {
125
+ return getInstance (start ) != null && getInstance (start ).hikariDataSource != null ;
126
+ }
127
+
128
+ static void initPool (Start start , boolean shouldWait ) throws DbInitException {
129
+ if (isAlreadyInitialised (start )) {
125
130
return ;
126
131
}
127
132
if (Thread .currentThread () != start .mainThread ) {
128
- throw new QuitProgramFromPluginException ("Should not come here" );
133
+ throw new DbInitException ("Should not come here" );
129
134
}
130
135
Logging .info (start , "Setting up PostgreSQL connection pool." , true );
131
136
boolean longMessagePrinted = false ;
132
137
long maxTryTime = System .currentTimeMillis () + getTimeToWaitToInit (start );
133
- String errorMessage = "Error connecting to PostgreSQL instance. Please make sure that PostgreSQL is running and that "
134
- + "you have" + " specified the correct values for ('postgresql_host' and 'postgresql_port') or for "
135
- + "'postgresql_connection_uri'" ;
138
+ String errorMessage =
139
+ "Error connecting to PostgreSQL instance. Please make sure that PostgreSQL is running and that "
140
+ + "you have" +
141
+ " specified the correct values for ('postgresql_host' and 'postgresql_port') or for "
142
+ + "'postgresql_connection_uri'" ;
136
143
try {
144
+ ConnectionPool con = new ConnectionPool (start );
145
+ start .getResourceDistributor ().setResource (RESOURCE_KEY , con );
137
146
while (true ) {
138
147
try {
139
- start . getResourceDistributor (). setResource ( RESOURCE_KEY , new ConnectionPool ( start ) );
148
+ con . initialiseHikariDataSource ( );
140
149
break ;
141
150
} catch (Exception e ) {
151
+ if (!shouldWait ) {
152
+ throw new DbInitException (e );
153
+ }
142
154
if (e .getMessage ().contains ("Connection to" ) && e .getMessage ().contains ("refused" )
143
155
|| e .getMessage ().contains ("the database system is starting up" )) {
144
156
start .handleKillSignalForWhenItHappens ();
145
157
if (System .currentTimeMillis () > maxTryTime ) {
146
- throw new QuitProgramFromPluginException (errorMessage );
158
+ throw new DbInitException (errorMessage );
147
159
}
148
160
if (!longMessagePrinted ) {
149
161
longMessagePrinted = true ;
@@ -160,10 +172,10 @@ static void initPool(Start start) {
160
172
}
161
173
Thread .sleep (getRetryIntervalIfInitFails (start ));
162
174
} catch (InterruptedException ex ) {
163
- throw new QuitProgramFromPluginException (errorMessage );
175
+ throw new DbInitException (errorMessage );
164
176
}
165
177
} else {
166
- throw e ;
178
+ throw new DbInitException ( e ) ;
167
179
}
168
180
}
169
181
}
@@ -174,19 +186,28 @@ static void initPool(Start start) {
174
186
175
187
public static Connection getConnection (Start start ) throws SQLException {
176
188
if (getInstance (start ) == null ) {
177
- throw new QuitProgramFromPluginException ("Please call initPool before getConnection" );
189
+ throw new IllegalStateException ("Please call initPool before getConnection" );
178
190
}
179
191
if (!start .enabled ) {
180
192
throw new SQLException ("Storage layer disabled" );
181
193
}
182
- return ConnectionPool .hikariDataSource .getConnection ();
194
+ if (getInstance (start ).hikariDataSource == null ) {
195
+ getInstance (start ).initialiseHikariDataSource ();
196
+ }
197
+ return getInstance (start ).hikariDataSource .getConnection ();
183
198
}
184
199
185
200
static void close (Start start ) {
186
201
if (getInstance (start ) == null ) {
187
202
return ;
188
203
}
189
- ConnectionPool .hikariDataSource .close ();
190
- ConnectionPool .hikariDataSource = null ;
204
+ if (getInstance (start ).hikariDataSource != null ) {
205
+ try {
206
+ getInstance (start ).hikariDataSource .close ();
207
+ } finally {
208
+ // we mark it as null so that next time it's being initialised, it will be initialised again
209
+ getInstance (start ).hikariDataSource = null ;
210
+ }
211
+ }
191
212
}
192
213
}
0 commit comments