This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 201328786d3a5e4fcb33f18c2763010fe9ccd32e Author: Tran Tien Duc <[email protected]> AuthorDate: Wed May 15 16:56:16 2019 +0700 JAMES-2763 CassandraSchemaVersion StartUpCheck --- .../CassandraSchemaVersionStartUpCheck.java | 116 +++++++++++++++++++++ .../modules/mailbox/CassandraSessionModule.java | 54 +--------- .../CassandraSchemaVersionStartUpCheckTest.java} | 42 +++++--- .../org/apache/james/StartUpChecksPerformer.java | 15 ++- 4 files changed, 159 insertions(+), 68 deletions(-) diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraSchemaVersionStartUpCheck.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraSchemaVersionStartUpCheck.java new file mode 100644 index 0000000..0e6b24a --- /dev/null +++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraSchemaVersionStartUpCheck.java @@ -0,0 +1,116 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 * + * * + * http://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.apache.james.modules.mailbox; + +import org.apache.james.StartUpChecksPerformer; +import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.inject.Inject; + +public class CassandraSchemaVersionStartUpCheck implements StartUpChecksPerformer.StartUpCheck { + + private static final Logger LOGGER = LoggerFactory.getLogger(CassandraSchemaVersionStartUpCheck.class); + static final String CHECK_NAME = "CassandraSchemaVersionStartUpCheck"; + + private final CassandraSchemaVersionManager versionManager; + + @Inject + public CassandraSchemaVersionStartUpCheck(CassandraSchemaVersionManager versionManager) { + this.versionManager = versionManager; + } + + @Override + public CheckResult check() { + CassandraSchemaVersionManager.SchemaState schemaState = versionManager.computeSchemaState(); + switch (schemaState) { + case TOO_OLD: + return checkTooOldState(); + case TOO_RECENT: + return checkTooRecentState(); + case UP_TO_DATE: + return checkUpToDateState(); + case UPGRADABLE: + return checkUpgradeAbleState(); + default: + String unknownSchemaStateMessage = "Unknown schema state " + schemaState; + LOGGER.error(unknownSchemaStateMessage); + return CheckResult.builder() + .checkName(CHECK_NAME) + .resultType(ResultType.BAD) + .description(unknownSchemaStateMessage) + .build(); + } + } + + private CheckResult checkUpgradeAbleState() { + String upgradeVersionMessage = + String.format("Current schema version is %d. Recommended version is %d", + versionManager.computeVersion().getValue(), + versionManager.getMaximumSupportedVersion().getValue()); + LOGGER.warn(upgradeVersionMessage); + return CheckResult.builder() + .checkName(CHECK_NAME) + .resultType(ResultType.GOOD) + .description(upgradeVersionMessage) + .build(); + } + + private CheckResult checkUpToDateState() { + String message = "Schema version is up-to-date"; + LOGGER.info(message); + return CheckResult.builder() + .checkName(CHECK_NAME) + .resultType(ResultType.GOOD) + .description(message) + .build(); + } + + private CheckResult checkTooRecentState() { + String versionExceedMaximumSupportedMessage = + String.format("Current schema version is %d whereas the maximum supported version is %d. " + + "Recommended version is %d.", + versionManager.computeVersion().getValue(), + versionManager.getMaximumSupportedVersion().getValue(), + versionManager.getMaximumSupportedVersion().getValue()); + LOGGER.error(versionExceedMaximumSupportedMessage); + return CheckResult.builder() + .checkName(CHECK_NAME) + .resultType(ResultType.BAD) + .description(versionExceedMaximumSupportedMessage) + .build(); + } + + private CheckResult checkTooOldState() { + String versionToOldMessage = + String.format("Current schema version is %d whereas minimum required version is %d. " + + "Recommended version is %d", + versionManager.computeVersion().getValue(), + versionManager.getMinimumSupportedVersion().getValue(), + versionManager.getMaximumSupportedVersion().getValue()); + LOGGER.error(versionToOldMessage); + return CheckResult.builder() + .checkName(CHECK_NAME) + .resultType(ResultType.BAD) + .description(versionToOldMessage) + .build(); + } +} diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraSessionModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraSessionModule.java index 1613dfe..951a328 100644 --- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraSessionModule.java +++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraSessionModule.java @@ -19,11 +19,11 @@ package org.apache.james.modules.mailbox; import java.io.FileNotFoundException; -import java.util.List; import java.util.Set; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; +import org.apache.james.StartUpChecksPerformer; import org.apache.james.backends.cassandra.components.CassandraModule; import org.apache.james.backends.cassandra.init.CassandraZonedDateTimeModule; import org.apache.james.backends.cassandra.init.SessionWithInitializedTablesFactory; @@ -33,14 +33,11 @@ import org.apache.james.backends.cassandra.utils.CassandraHealthCheck; import org.apache.james.backends.cassandra.utils.CassandraUtils; import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO; import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager; -import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager.SchemaState; import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule; import org.apache.james.core.healthcheck.HealthCheck; -import org.apache.james.lifecycle.api.Startable; import org.apache.james.mailbox.store.BatchSizes; import org.apache.james.server.CassandraProbe; import org.apache.james.util.Host; -import org.apache.james.utils.ConfigurationPerformer; import org.apache.james.utils.GuiceProbe; import org.apache.james.utils.PropertiesProvider; import org.slf4j.Logger; @@ -49,9 +46,7 @@ import org.slf4j.LoggerFactory; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Session; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; import com.google.inject.AbstractModule; -import com.google.inject.Inject; import com.google.inject.Provides; import com.google.inject.Scopes; import com.google.inject.Singleton; @@ -79,7 +74,8 @@ public class CassandraSessionModule extends AbstractModule { bind(CassandraSchemaVersionManager.class).in(Scopes.SINGLETON); bind(CassandraSchemaVersionDAO.class).in(Scopes.SINGLETON); - Multibinder.newSetBinder(binder(), ConfigurationPerformer.class).addBinding().to(CassandraSchemaChecker.class); + Multibinder.newSetBinder(binder(), StartUpChecksPerformer.StartUpCheck.class) + .addBinding().to(CassandraSchemaVersionStartUpCheck.class); Multibinder.newSetBinder(binder(), GuiceProbe.class).addBinding().to(CassandraProbe.class); @@ -136,48 +132,4 @@ public class CassandraSessionModule extends AbstractModule { .build(); } } - - public static class CassandraSchemaChecker implements ConfigurationPerformer { - private final CassandraSchemaVersionManager versionManager; - - @Inject - public CassandraSchemaChecker(CassandraSchemaVersionManager versionManager) { - this.versionManager = versionManager; - } - - @Override - public void initModule() { - SchemaState schemaState = versionManager.computeSchemaState(); - switch (schemaState) { - case TOO_OLD: - throw new IllegalStateException( - String.format("Current schema version is %d whereas minimum required version is %d. " + - "Recommended version is %d", - versionManager.computeVersion().getValue(), - versionManager.getMinimumSupportedVersion().getValue(), - versionManager.getMaximumSupportedVersion().getValue())); - case TOO_RECENT: - throw new IllegalStateException( - String.format("Current schema version is %d whereas the minimum supported version is %d. " + - "Recommended version is %d.", - versionManager.computeVersion().getValue(), - versionManager.getMinimumSupportedVersion().getValue(), - versionManager.getMaximumSupportedVersion().getValue())); - case UP_TO_DATE: - LOGGER.info("Schema version is up-to-date"); - return; - case UPGRADABLE: - LOGGER.warn("Current schema version is {}. Recommended version is {}", versionManager.computeVersion(), - versionManager.getMaximumSupportedVersion()); - return; - default: - throw new IllegalStateException("Unknown schema state " + schemaState); - } - } - - @Override - public List<Class<? extends Startable>> forClasses() { - return ImmutableList.of(); - } - } } diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraVersionCheckingTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/modules/mailbox/CassandraSchemaVersionStartUpCheckTest.java similarity index 77% rename from server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraVersionCheckingTest.java rename to server/container/guice/cassandra-guice/src/test/java/org/apache/james/modules/mailbox/CassandraSchemaVersionStartUpCheckTest.java index d7cb7d1..a653310 100644 --- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraVersionCheckingTest.java +++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/modules/mailbox/CassandraSchemaVersionStartUpCheckTest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * * under the License. * ****************************************************************/ -package org.apache.james; +package org.apache.james.modules.mailbox; import static org.apache.james.CassandraJamesServerMain.ALL_BUT_JMX_CASSANDRA_MODULE; import static org.assertj.core.api.Assertions.assertThat; @@ -31,6 +31,12 @@ import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Optional; +import org.apache.james.CassandraExtension; +import org.apache.james.DockerElasticSearchExtension; +import org.apache.james.GuiceJamesServer; +import org.apache.james.JamesServerBuilder; +import org.apache.james.JamesServerExtension; +import org.apache.james.StartUpChecksPerformer.StartUpChecksException; import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO; import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager; import org.apache.james.backends.cassandra.versions.SchemaVersion; @@ -45,9 +51,10 @@ import org.junit.jupiter.api.extension.RegisterExtension; import reactor.core.publisher.Mono; -class CassandraVersionCheckingTest { +class CassandraSchemaVersionStartUpCheckTest { private static final int LIMIT_TO_10_MESSAGES = 10; private static final String LOCAL_HOST = "127.0.0.1"; + private static final String EXPECTED_SERVER_CONNECTED_MESSAGE = "* OK JAMES IMAP4rev1 Server"; private static final SchemaVersion MIN_VERSION = new SchemaVersion(2); private static final SchemaVersion MAX_VERSION = new SchemaVersion(4); @@ -85,7 +92,9 @@ class CassandraVersionCheckingTest { when(versionDAO.getCurrentSchemaVersion()) .thenReturn(Mono.just(Optional.of(MAX_VERSION))); - assertThatServerStartCorrectly(server); + server.start(); + assertThat(responseAfterConnectTo(server)) + .startsWith(EXPECTED_SERVER_CONNECTED_MESSAGE); } @Test @@ -93,7 +102,9 @@ class CassandraVersionCheckingTest { when(versionDAO.getCurrentSchemaVersion()) .thenReturn(Mono.just(Optional.of(MIN_VERSION.next()))); - assertThatServerStartCorrectly(server); + server.start(); + assertThat(responseAfterConnectTo(server)) + .startsWith(EXPECTED_SERVER_CONNECTED_MESSAGE); } @Test @@ -101,7 +112,9 @@ class CassandraVersionCheckingTest { when(versionDAO.getCurrentSchemaVersion()) .thenReturn(Mono.just(Optional.of(MIN_VERSION))); - assertThatServerStartCorrectly(server); + server.start(); + assertThat(responseAfterConnectTo(server)) + .startsWith(EXPECTED_SERVER_CONNECTED_MESSAGE); } @Test @@ -109,7 +122,11 @@ class CassandraVersionCheckingTest { when(versionDAO.getCurrentSchemaVersion()) .thenReturn(Mono.just(Optional.of(MIN_VERSION.previous()))); - assertThatThrownBy(server::start).isInstanceOf(IllegalStateException.class); + assertThatThrownBy(server::start) + .isInstanceOfSatisfying( + StartUpChecksException.class, + exception -> assertThat(exception.badCheckNames()) + .containsOnly(CassandraSchemaVersionStartUpCheck.CHECK_NAME)); } @Test @@ -117,17 +134,16 @@ class CassandraVersionCheckingTest { when(versionDAO.getCurrentSchemaVersion()) .thenReturn(Mono.just(Optional.of(MAX_VERSION.next()))); - assertThatThrownBy(server::start).isInstanceOf(IllegalStateException.class); + assertThatThrownBy(server::start) + .isInstanceOfSatisfying( + StartUpChecksException.class, + exception -> assertThat(exception.badCheckNames()) + .containsOnly(CassandraSchemaVersionStartUpCheck.CHECK_NAME)); } - private void assertThatServerStartCorrectly(GuiceJamesServer server) throws Exception { - server.start(); + private String responseAfterConnectTo(GuiceJamesServer server) throws IOException { socketChannel.connect(new InetSocketAddress(LOCAL_HOST, server.getProbe(ImapGuiceProbe.class).getImapPort())); - assertThat(getServerConnectionResponse(socketChannel)) - .startsWith("* OK JAMES IMAP4rev1 Server"); - } - private String getServerConnectionResponse(SocketChannel socketChannel) throws IOException { ByteBuffer byteBuffer = ByteBuffer.allocate(1000); socketChannel.read(byteBuffer); byte[] bytes = byteBuffer.array(); diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/StartUpChecksPerformer.java b/server/container/guice/guice-common/src/main/java/org/apache/james/StartUpChecksPerformer.java index 02d895e..e047e97 100644 --- a/server/container/guice/guice-common/src/main/java/org/apache/james/StartUpChecksPerformer.java +++ b/server/container/guice/guice-common/src/main/java/org/apache/james/StartUpChecksPerformer.java @@ -65,6 +65,13 @@ public class StartUpChecksPerformer { public List<StartUpCheck.CheckResult> getBadChecks() { return badChecks; } + + @VisibleForTesting + public List<String> badCheckNames() { + return badChecks.stream() + .map(StartUpCheck.CheckResult::getName) + .collect(Guavate.toImmutableList()); + } } public interface StartUpCheck { @@ -75,19 +82,19 @@ public class StartUpChecksPerformer { class CheckResult { - static class Builder { + public static class Builder { @FunctionalInterface - interface RequireCheckName { + public interface RequireCheckName { RequireResultType checkName(String name); } @FunctionalInterface - interface RequireResultType { + public interface RequireResultType { ReadyToBuild resultType(ResultType resultType); } - static class ReadyToBuild { + public static class ReadyToBuild { private final String name; private final ResultType resultType; private Optional<String> description; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
