2323import java .util .LinkedHashSet ;
2424import java .util .List ;
2525import java .util .Set ;
26+ import java .util .concurrent .CompletionStage ;
2627import java .util .function .IntFunction ;
2728import java .util .stream .Collectors ;
2829import java .util .stream .Stream ;
5758
5859import com .datastax .oss .driver .api .core .CqlSession ;
5960import com .datastax .oss .driver .api .core .CqlSessionBuilder ;
61+ import com .datastax .oss .driver .internal .core .util .concurrent .CompletableFutures ;
6062
6163/**
6264 * 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
108110
109111 private SchemaAction schemaAction = SchemaAction .NONE ;
110112
113+ private boolean suspendLifecycleSchemaRefresh = false ;
114+
111115 private @ Nullable SessionBuilderConfigurer sessionBuilderConfigurer ;
112116
113117 private IntFunction <Collection <InetSocketAddress >> contactPoints = port -> createInetSocketAddresses (
@@ -348,8 +352,8 @@ protected CassandraMappingContext getMappingContext() {
348352 * Set the {@link SchemaAction}.
349353 *
350354 * @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.
353357 */
354358 @ Deprecated
355359 public void setSchemaAction (SchemaAction schemaAction ) {
@@ -366,6 +370,24 @@ public SchemaAction getSchemaAction() {
366370 return this .schemaAction ;
367371 }
368372
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+
369391 /**
370392 * Returns a reference to the connected Cassandra {@link CqlSession}.
371393 *
@@ -455,20 +477,30 @@ public void afterPropertiesSet() {
455477
456478 this .session = buildSession (sessionBuilder );
457479
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 ));
467497 }
468498
469- if (this . systemSession .isSchemaMetadataEnabled ()) {
470- this . systemSession .refreshSchema ( );
499+ if (systemSession .isSchemaMetadataEnabled ()) {
500+ futures . add ( systemSession .refreshSchemaAsync () );
471501 }
502+
503+ futures .forEach (CompletableFutures ::getUninterruptibly );
472504 }
473505
474506 protected CqlSessionBuilder buildBuilder () {
@@ -536,7 +568,15 @@ private void initializeCluster(CqlSession session) {
536568 keyspaceStartupSpecifications .addAll (this .keyspaceCreations );
537569 keyspaceStartupSpecifications .addAll (this .keyspaceAlterations );
538570
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+ }
540580 }
541581
542582 /**
@@ -564,7 +604,7 @@ private void generateSpecifications(Collection<KeyspaceActionSpecification> spec
564604 }
565605
566606 /**
567- * Perform the configure {@link SchemaAction} using {@link CassandraMappingContext} metadata.
607+ * Perform the configured {@link SchemaAction} using {@link CassandraMappingContext} metadata.
568608 */
569609 protected void performSchemaAction () {
570610
@@ -664,8 +704,23 @@ public DataAccessException translateExceptionIfPossible(RuntimeException e) {
664704 public void destroy () {
665705
666706 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+
669724 closeSession ();
670725 closeSystemSession ();
671726 }
0 commit comments