55 */
66package org .hibernate .reactive .pool .impl ;
77
8+ import java .lang .invoke .MethodHandles ;
9+ import java .lang .invoke .VarHandle ;
810import java .sql .ResultSet ;
911import java .sql .SQLException ;
1012import java .util .List ;
2224import org .hibernate .reactive .pool .ReactiveConnectionPool ;
2325
2426import io .vertx .core .Future ;
27+ import io .vertx .core .internal .ContextInternal ;
2528import io .vertx .sqlclient .DatabaseException ;
2629import io .vertx .sqlclient .Pool ;
2730import io .vertx .sqlclient .Row ;
3033import io .vertx .sqlclient .Tuple ;
3134import io .vertx .sqlclient .spi .DatabaseMetadata ;
3235
33- import static org .hibernate .reactive .util .impl .CompletionStages .completedFuture ;
3436import static org .hibernate .reactive .util .impl .CompletionStages .rethrow ;
3537import static org .hibernate .reactive .util .impl .CompletionStages .voidFuture ;
3638
@@ -123,12 +125,16 @@ public CompletionStage<ReactiveConnection> getConnection(String tenantId, SqlExc
123125 }
124126
125127 private CompletionStage <ReactiveConnection > getConnectionFromPool (Pool pool ) {
126- return completionStage ( pool .getConnection ().map ( this ::newConnection ), ReactiveConnection ::close );
128+ return completeFuture (
129+ pool .getConnection ().map ( this ::newConnection ),
130+ ReactiveConnection ::close
131+ );
127132 }
128133
129134 private CompletionStage <ReactiveConnection > getConnectionFromPool (Pool pool , SqlExceptionHelper sqlExceptionHelper ) {
130- return completionStage (
131- pool .getConnection ().map ( sqlConnection -> newConnection ( sqlConnection , sqlExceptionHelper ) ),
135+ return completeFuture (
136+ pool .getConnection ()
137+ .map ( sqlConnection -> newConnection ( sqlConnection , sqlExceptionHelper ) ),
132138 ReactiveConnection ::close
133139 );
134140 }
@@ -189,8 +195,8 @@ private void feedback(String sql) {
189195 /**
190196 * @param onCancellation invoke when converted {@link java.util.concurrent.CompletionStage} cancellation.
191197 */
192- private <T > CompletionStage <T > completionStage (Future <T > future , Consumer <T > onCancellation ) {
193- CompletableFuture <T > completableFuture = new CompletableFuture <>();
198+ private <T > CompletionStage <T > completeFuture (Future <T > future , Consumer <T > onCancellation ) {
199+ final CompletableFuture <T > completableFuture = new CompletableFuture <>();
194200 future .onComplete ( ar -> {
195201 if ( ar .succeeded () ) {
196202 if ( completableFuture .isCancelled () ) {
@@ -210,13 +216,32 @@ private SqlClientConnection newConnection(SqlConnection connection) {
210216 }
211217
212218 private SqlClientConnection newConnection (SqlConnection connection , SqlExceptionHelper sqlExceptionHelper ) {
213- return new SqlClientConnection ( connection , getPool (), getSqlStatementLogger (), sqlExceptionHelper );
219+ return new SqlClientConnection (
220+ connection ,
221+ getPool (),
222+ getSqlStatementLogger (),
223+ sqlExceptionHelper ,
224+ ContextInternal .current ()
225+ );
214226 }
215227
216228 private static class ProxyConnection implements ReactiveConnection {
229+
230+ private static final VarHandle OPENED_HANDLE ;
231+
232+ static {
233+ try {
234+ MethodHandles .Lookup lookup = MethodHandles .lookup ();
235+ OPENED_HANDLE = lookup .findVarHandle ( ProxyConnection .class , "opened" , boolean .class );
236+ }
237+ catch (ReflectiveOperationException e ) {
238+ throw new ExceptionInInitializerError ( e );
239+ }
240+ }
241+
217242 private final Supplier <CompletionStage <ReactiveConnection >> connectionSupplier ;
218- private Integer batchSize ;
219- private ReactiveConnection connection ;
243+ private final CompletableFuture < ReactiveConnection > connectionFuture = new CompletableFuture <>() ;
244+ private volatile boolean opened = false ;
220245
221246 public ProxyConnection (Supplier <CompletionStage <ReactiveConnection >> connectionSupplier ) {
222247 this .connectionSupplier = connectionSupplier ;
@@ -225,29 +250,35 @@ public ProxyConnection(Supplier<CompletionStage<ReactiveConnection>> connectionS
225250 /**
226251 * @return the existing {@link ReactiveConnection}, or open a new one
227252 */
228- CompletionStage <ReactiveConnection > connection () {
229- if ( connection == null ) {
230- return connectionSupplier .get ()
231- .thenApply ( conn -> {
232- if ( batchSize != null ) {
233- conn .withBatchSize ( batchSize );
234- }
235- connection = conn ;
236- return connection ;
237- } );
253+ private CompletionStage <ReactiveConnection > connection () {
254+ if ( opened ) {
255+ return connectionFuture ;
256+ }
257+ if ( OPENED_HANDLE .compareAndSet ( this , false , true ) ) {
258+ connectionSupplier .get ().whenComplete ( (connection , throwable ) -> {
259+ if ( throwable != null ) {
260+ connectionFuture .completeExceptionally ( throwable );
261+ }
262+ else {
263+ connectionFuture .complete ( connection );
264+ }
265+ } );
238266 }
239- return completedFuture ( connection ) ;
267+ return connectionFuture ;
240268 }
241269
242270 @ Override
243271 public boolean isTransactionInProgress () {
244- return connection != null && connection .isTransactionInProgress ();
272+ ReactiveConnection reactiveConnection = connectionFuture .getNow ( null );
273+ return reactiveConnection != null && reactiveConnection .isTransactionInProgress ();
245274 }
246275
247276 @ Override
248277 public DatabaseMetadata getDatabaseMetadata () {
249- Objects .requireNonNull ( connection , "Database metadata not available until the connection is opened" );
250- return connection .getDatabaseMetadata ();
278+ return Objects .requireNonNull (
279+ connectionFuture .getNow ( null ),
280+ "Database metadata not available until the connection is opened"
281+ ).getDatabaseMetadata ();
251282 }
252283
253284 @ Override
@@ -356,13 +387,8 @@ public CompletionStage<Void> rollbackTransaction() {
356387 }
357388
358389 @ Override
359- public ReactiveConnection withBatchSize (int batchSize ) {
360- if ( connection == null ) {
361- this .batchSize = batchSize ;
362- }
363- else {
364- connection = connection .withBatchSize ( batchSize );
365- }
390+ public ProxyConnection withBatchSize (int batchSize ) {
391+ connectionFuture .thenApply ( reactiveConnection -> reactiveConnection .withBatchSize ( batchSize ) );
366392 return this ;
367393 }
368394
@@ -373,8 +399,8 @@ public CompletionStage<Void> executeBatch() {
373399
374400 @ Override
375401 public CompletionStage <Void > close () {
376- return connection != null
377- ? connection . close (). thenAccept ( v -> connection = null )
402+ return opened
403+ ? connectionFuture . getNow ( null ). close ( )
378404 : voidFuture ();
379405 }
380406 }
0 commit comments