23
23
import java .util .LinkedHashSet ;
24
24
import java .util .List ;
25
25
import java .util .Set ;
26
+ import java .util .concurrent .CompletionStage ;
26
27
import java .util .function .IntFunction ;
27
28
import java .util .stream .Collectors ;
28
29
import java .util .stream .Stream ;
57
58
58
59
import com .datastax .oss .driver .api .core .CqlSession ;
59
60
import com .datastax .oss .driver .api .core .CqlSessionBuilder ;
61
+ import com .datastax .oss .driver .internal .core .util .concurrent .CompletableFutures ;
60
62
61
63
/**
62
64
* Factory for creating and configuring a Cassandra {@link CqlSession}, which is a thread-safe singleton. As such, it is
@@ -108,6 +110,8 @@ public class CqlSessionFactoryBean
108
110
109
111
private SchemaAction schemaAction = SchemaAction .NONE ;
110
112
113
+ private boolean suspendLifecycleSchemaRefresh = false ;
114
+
111
115
private @ Nullable SessionBuilderConfigurer sessionBuilderConfigurer ;
112
116
113
117
private IntFunction <Collection <InetSocketAddress >> contactPoints = port -> createInetSocketAddresses (
@@ -348,8 +352,8 @@ protected CassandraMappingContext getMappingContext() {
348
352
* Set the {@link SchemaAction}.
349
353
*
350
354
* @param schemaAction must not be {@literal null}.
351
- * @deprecated Use {@link CassandraSessionFactoryBean } with
352
- * {@link CassandraSessionFactoryBean #setSchemaAction(SchemaAction)} instead.
355
+ * @deprecated Use {@link SessionFactoryFactoryBean } with
356
+ * {@link SessionFactoryFactoryBean #setSchemaAction(SchemaAction)} instead.
353
357
*/
354
358
@ Deprecated
355
359
public void setSchemaAction (SchemaAction schemaAction ) {
@@ -366,6 +370,24 @@ public SchemaAction getSchemaAction() {
366
370
return this .schemaAction ;
367
371
}
368
372
373
+ /**
374
+ * Set whether to suspend schema refresh settings during {@link #afterPropertiesSet()} and {@link #destroy()}
375
+ * lifecycle callbacks. Disabled by default to use schema metadata settings of the session configuration. When enabled
376
+ * (set to {@code true}), then schema refresh during lifecycle methods is suspended until finishing schema actions to
377
+ * avoid periodic schema refreshes for each DDL statement.
378
+ * <p>
379
+ * Suspending schema refresh can be useful to delay schema agreement until the entire schema is created. Note that
380
+ * disabling schema refresh may interfere with schema actions. {@link SchemaAction#RECREATE_DROP_UNUSED} and
381
+ * mapping-based schema creation rely on schema metadata.
382
+ *
383
+ * @param suspendLifecycleSchemaRefresh {@code true} to suspend the schema refresh during lifecycle callbacks;
384
+ * {@code false} otherwise to retain the session schema refresh configuration.
385
+ * @since 2.7
386
+ */
387
+ public void setSuspendLifecycleSchemaRefresh (boolean suspendLifecycleSchemaRefresh ) {
388
+ this .suspendLifecycleSchemaRefresh = suspendLifecycleSchemaRefresh ;
389
+ }
390
+
369
391
/**
370
392
* Returns a reference to the connected Cassandra {@link CqlSession}.
371
393
*
@@ -455,20 +477,30 @@ public void afterPropertiesSet() {
455
477
456
478
this .session = buildSession (sessionBuilder );
457
479
458
- try {
459
- SchemaRefreshUtils .withDisabledSchema (this .session , () -> {
460
- executeCql (getStartupScripts ().stream (), this .session );
461
- performSchemaAction ();
462
- });
463
- } catch (RuntimeException e ) {
464
- throw e ;
465
- } catch (Exception e ) {
466
- throw new IllegalStateException ("Unexpected checked exception thrown" , e );
480
+ initializeSchema (this .systemSession , this .session );
481
+ }
482
+
483
+ private void initializeSchema (CqlSession systemSession , CqlSession session ) {
484
+
485
+ Runnable schemaActionRunnable = () -> {
486
+
487
+ executeCql (getStartupScripts ().stream (), session );
488
+ performSchemaAction ();
489
+ };
490
+
491
+ List <CompletionStage <?>> futures = new ArrayList <>(2 );
492
+
493
+ if (this .suspendLifecycleSchemaRefresh ) {
494
+ futures .add (SchemaUtils .withSuspendedAsyncSchemaRefresh (session , schemaActionRunnable ));
495
+ } else {
496
+ futures .add (SchemaUtils .withAsyncSchemaRefresh (session , schemaActionRunnable ));
467
497
}
468
498
469
- if (this . systemSession .isSchemaMetadataEnabled ()) {
470
- this . systemSession .refreshSchema ( );
499
+ if (systemSession .isSchemaMetadataEnabled ()) {
500
+ futures . add ( systemSession .refreshSchemaAsync () );
471
501
}
502
+
503
+ futures .forEach (CompletableFutures ::getUninterruptibly );
472
504
}
473
505
474
506
protected CqlSessionBuilder buildBuilder () {
@@ -536,7 +568,15 @@ private void initializeCluster(CqlSession session) {
536
568
keyspaceStartupSpecifications .addAll (this .keyspaceCreations );
537
569
keyspaceStartupSpecifications .addAll (this .keyspaceAlterations );
538
570
539
- executeSpecificationsAndScripts (keyspaceStartupSpecifications , this .keyspaceStartupScripts , session );
571
+ Runnable schemaActionRunnable = () -> {
572
+ executeSpecificationsAndScripts (keyspaceStartupSpecifications , this .keyspaceStartupScripts , session );
573
+ };
574
+
575
+ if (this .suspendLifecycleSchemaRefresh ) {
576
+ SchemaUtils .withSuspendedAsyncSchemaRefresh (session , schemaActionRunnable );
577
+ } else {
578
+ schemaActionRunnable .run ();
579
+ }
540
580
}
541
581
542
582
/**
@@ -564,7 +604,7 @@ private void generateSpecifications(Collection<KeyspaceActionSpecification> spec
564
604
}
565
605
566
606
/**
567
- * Perform the configure {@link SchemaAction} using {@link CassandraMappingContext} metadata.
607
+ * Perform the configured {@link SchemaAction} using {@link CassandraMappingContext} metadata.
568
608
*/
569
609
protected void performSchemaAction () {
570
610
@@ -664,8 +704,23 @@ public DataAccessException translateExceptionIfPossible(RuntimeException e) {
664
704
public void destroy () {
665
705
666
706
if (this .session != null ) {
667
- executeCql (getShutdownScripts ().stream (), this .session );
668
- executeSpecificationsAndScripts (this .keyspaceDrops , this .keyspaceShutdownScripts , this .systemSession );
707
+
708
+ Runnable schemaActionRunnable = () -> {
709
+ executeCql (getShutdownScripts ().stream (), this .session );
710
+ };
711
+
712
+ Runnable systemSchemaActionRunnable = () -> {
713
+ executeSpecificationsAndScripts (this .keyspaceDrops , this .keyspaceShutdownScripts , this .systemSession );
714
+ };
715
+
716
+ if (this .suspendLifecycleSchemaRefresh ) {
717
+ SchemaUtils .withSuspendedAsyncSchemaRefresh (this .session , schemaActionRunnable );
718
+ SchemaUtils .withSuspendedAsyncSchemaRefresh (this .systemSession , systemSchemaActionRunnable );
719
+ } else {
720
+ schemaActionRunnable .run ();
721
+ systemSchemaActionRunnable .run ();
722
+ }
723
+
669
724
closeSession ();
670
725
closeSystemSession ();
671
726
}
0 commit comments