From 1d1505ab9aca4ab4666b835fb8bdba9344658ccd Mon Sep 17 00:00:00 2001 From: Ammar Khaku Date: Sun, 17 Apr 2022 14:59:33 -0700 Subject: [PATCH] Disable schema metadata when performing SchemaActions. Additionally, don't force refresh schemas if schema metadata is disabled. Closes: #990 Closes: #1253 Original pull request: #1255. --- .../config/CqlSessionFactoryBean.java | 18 +++-- .../cassandra/config/SchemaRefreshUtils.java | 48 ++++++++++++++ .../config/SessionFactoryFactoryBean.java | 5 +- .../config/SchemaRefreshUtilsUnitTests.java | 66 +++++++++++++++++++ 4 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/SchemaRefreshUtils.java create mode 100644 spring-data-cassandra/src/test/java/org/springframework/data/cassandra/config/SchemaRefreshUtilsUnitTests.java diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CqlSessionFactoryBean.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CqlSessionFactoryBean.java index 3f42ae2ec..dff59a893 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CqlSessionFactoryBean.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CqlSessionFactoryBean.java @@ -67,6 +67,7 @@ import com.datastax.oss.driver.api.core.CqlSessionBuilder; * @author John Blum * @author Mark Paluch * @author Tomasz Lelek + * @author Ammar Khaku * @since 3.0 */ public class CqlSessionFactoryBean @@ -450,11 +451,20 @@ public class CqlSessionFactoryBean this.session = buildSession(sessionBuilder); - executeCql(getStartupScripts().stream(), this.session); - performSchemaAction(); + try { + SchemaRefreshUtils.withDisabledSchema(this.session, () -> { + executeCql(getStartupScripts().stream(), this.session); + performSchemaAction(); + }); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Unexpected checked exception thrown", e); + } - this.systemSession.refreshSchema(); - this.session.refreshSchema(); + if (this.systemSession.isSchemaMetadataEnabled()) { + this.systemSession.refreshSchema(); + } } protected CqlSessionBuilder buildBuilder() { diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/SchemaRefreshUtils.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/SchemaRefreshUtils.java new file mode 100644 index 000000000..beb5c144d --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/SchemaRefreshUtils.java @@ -0,0 +1,48 @@ +/* + * Copyright 2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.config; + +import com.datastax.oss.driver.api.core.session.Session; + +/** + * Utility methods for executing schema actions with refresh disabled. + * + * @author Ammar Khaku + */ +class SchemaRefreshUtils { + @FunctionalInterface + interface ThrowingRunnable { + void run() throws Exception; + } + + /** + * Programmatically disables schema refreshes on the session and runs the provided Runnable, + * taking care to restore the previous state of schema refresh config on the provided session. + * Note that the session could have had schema refreshes enabled/disabled either + * programmatically or via config. + */ + static void withDisabledSchema(Session session, ThrowingRunnable r) throws Exception { + boolean schemaEnabledPreviously = session.isSchemaMetadataEnabled(); + session.setSchemaMetadataEnabled(false); + r.run(); + session.setSchemaMetadataEnabled(null); // triggers schema refresh if results in true + if (schemaEnabledPreviously != session.isSchemaMetadataEnabled()) { + // user may have set it programmatically so set it back programmatically + session.setSchemaMetadataEnabled(schemaEnabledPreviously); + } + } +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/SessionFactoryFactoryBean.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/SessionFactoryFactoryBean.java index 0f0d838d5..6e5fb8e76 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/SessionFactoryFactoryBean.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/SessionFactoryFactoryBean.java @@ -37,6 +37,7 @@ import com.datastax.oss.driver.api.core.CqlSession; * keyspace before applying {@link SchemaAction schema actions} such as creating user-defined types and tables. * * @author Mark Paluch + * @author Ammar Khaku * @since 3.0 * @see SessionFactoryInitializer */ @@ -128,9 +129,7 @@ public class SessionFactoryFactoryBean extends AbstractFactoryBean {}); + verify(session).setSchemaMetadataEnabled(false); + verify(session).setSchemaMetadataEnabled(null); + } + + @Test + void withDisabledSchemaDisabledPreviously() throws Exception { + when(session.isSchemaMetadataEnabled()).thenReturn(false); + SchemaRefreshUtils.withDisabledSchema(session, () -> {}); + verify(session).setSchemaMetadataEnabled(false); + verify(session).setSchemaMetadataEnabled(null); + } + + @Test + void withDisabledSchemaDisabledProgrammaticallyPreviously() throws Exception { + when(session.isSchemaMetadataEnabled()).thenReturn(false).thenReturn(true); + SchemaRefreshUtils.withDisabledSchema(session, () -> {}); + verify(session, times(2)).setSchemaMetadataEnabled(false); + verify(session).setSchemaMetadataEnabled(null); + } + + @Test + void withDisabledSchemaEnabledProgrammaticallyPreviously() throws Exception { + when(session.isSchemaMetadataEnabled()).thenReturn(true).thenReturn(false); + SchemaRefreshUtils.withDisabledSchema(session, () -> {}); + verify(session).setSchemaMetadataEnabled(true); + verify(session).setSchemaMetadataEnabled(null); + } +}