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 e88a52e5120d6d51eba4706a500e4b3888134c42 Author: Gautier DI FOLCO <gdifo...@linagora.com> AuthorDate: Tue Jun 16 18:35:19 2020 +0200 JAMES-3224 Introduce CassandraConsistenciesConfiguration --- .../init/configuration/CassandraConfiguration.java | 79 +++++++++++++++++-- .../CassandraConsistenciesConfiguration.java | 90 ++++++++++++++++++++++ .../init/CassandraConfigurationReadingTest.java | 2 + .../cassandra/init/CassandraConfigurationTest.java | 20 +++++ .../CassandraConsistenciesConfigurationTest.java | 84 ++++++++++++++++++++ .../configuration-reader-test/cassandra.properties | 2 + .../destination/conf/cassandra.properties | 7 ++ .../destination/conf/cassandra.properties | 7 ++ .../destination/conf/cassandra.properties | 7 ++ .../destination/conf/cassandra.properties | 7 ++ .../modules/mailbox/CassandraSessionModule.java | 8 ++ src/site/xdoc/server/config-cassandra.xml | 6 ++ 12 files changed, 314 insertions(+), 5 deletions(-) diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConfiguration.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConfiguration.java index 2681d45..42bbce0 100644 --- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConfiguration.java +++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConfiguration.java @@ -21,17 +21,23 @@ package org.apache.james.backends.cassandra.init.configuration; import static java.lang.Math.toIntExact; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; import org.apache.commons.configuration2.Configuration; +import org.slf4j.LoggerFactory; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; public class CassandraConfiguration { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(CassandraConfiguration.class); + public static final int DEFAULT_MESSAGE_CHUNK_SIZE_ON_READ = 100; public static final int DEFAULT_EXPUNGE_BATCH_SIZE = 50; public static final int DEFAULT_UPDATE_FLAGS_BATCH_SIZE = 20; @@ -44,7 +50,10 @@ public class CassandraConfiguration { public static final int DEFAULT_BLOB_PART_SIZE = 100 * 1024; public static final int DEFAULT_ATTACHMENT_V2_MIGRATION_READ_TIMEOUT = toIntExact(TimeUnit.HOURS.toMillis(1)); public static final int DEFAULT_MESSAGE_ATTACHMENT_ID_MIGRATION_READ_TIMEOUT = toIntExact(TimeUnit.HOURS.toMillis(1)); - + public static final String DEFAULT_CONSISTENCY_LEVEL_REGULAR = "QUORUM"; + public static final String DEFAULT_CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION = "SERIAL"; + public static final List<String> VALID_CONSISTENCY_LEVEL_REGULAR = ImmutableList.of("QUORUM", "LOCAL_QUORUM", "EACH_QUORUM"); + public static final List<String> VALID_CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION = ImmutableList.of("SERIAL", "LOCAL_SERIAL"); private static final String MAILBOX_MAX_RETRY_ACL = "mailbox.max.retry.acl"; private static final String MAILBOX_MAX_RETRY_MODSEQ = "mailbox.max.retry.modseq"; @@ -57,6 +66,8 @@ public class CassandraConfiguration { private static final String BLOB_PART_SIZE = "mailbox.blob.part.size"; private static final String ATTACHMENT_V2_MIGRATION_READ_TIMEOUT = "attachment.v2.migration.read.timeout"; private static final String MESSAGE_ATTACHMENTID_READ_TIMEOUT = "message.attachmentids.read.timeout"; + private static final String CONSISTENCY_LEVEL_REGULAR = "cassandra.consistency_level.regular"; + private static final String CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION = "cassandra.consistency_level.lightweight_transaction"; public static final CassandraConfiguration DEFAULT_CONFIGURATION = builder().build(); @@ -72,6 +83,8 @@ public class CassandraConfiguration { private Optional<Integer> blobPartSize = Optional.empty(); private Optional<Integer> attachmentV2MigrationReadTimeout = Optional.empty(); private Optional<Integer> messageAttachmentIdsReadTimeout = Optional.empty(); + private Optional<String> consistencyLevelRegular = Optional.empty(); + private Optional<String> consistencyLevelLightweightTransaction = Optional.empty(); public Builder messageReadChunkSize(int value) { Preconditions.checkArgument(value > 0, "messageReadChunkSize needs to be strictly positive"); @@ -194,7 +207,39 @@ public class CassandraConfiguration { return this; } + public Builder consistencyLevelRegular(String value) { + Preconditions.checkArgument(VALID_CONSISTENCY_LEVEL_REGULAR.contains(value), + "consistencyLevelRegular needs to be one of the following: " + String.join(", ", VALID_CONSISTENCY_LEVEL_REGULAR)); + this.consistencyLevelRegular = Optional.of(value); + return this; + } + + public Builder consistencyLevelLightweightTransaction(String value) { + Preconditions.checkArgument(VALID_CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION.contains(value), + "consistencyLevelLightweightTransaction needs to be one of the following: " + String.join(", ", VALID_CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION)); + this.consistencyLevelLightweightTransaction = Optional.of(value); + return this; + } + + public Builder consistencyLevelRegular(Optional<String> value) { + value.ifPresent(this::consistencyLevelRegular); + return this; + } + + public Builder consistencyLevelLightweightTransaction(Optional<String> value) { + value.ifPresent(this::consistencyLevelLightweightTransaction); + return this; + } + public CassandraConfiguration build() { + String consistencyLevelRegular = this.consistencyLevelRegular.orElse(DEFAULT_CONSISTENCY_LEVEL_REGULAR); + String consistencyLevelLightweightTransaction = this.consistencyLevelLightweightTransaction.orElse(DEFAULT_CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION); + Predicate<String> isLocal = consistencyLevel -> consistencyLevel.startsWith("LOCAL_"); + if (isLocal.test(consistencyLevelRegular) != isLocal.test(consistencyLevelLightweightTransaction)) { + LOGGER.warn("The consistency levels may not be properly configured, one is local and the other not: " + + "regular = '{}' and lightweight transaction = '{}'", consistencyLevelRegular, consistencyLevelLightweightTransaction); + } + return new CassandraConfiguration(aclMaxRetry.orElse(DEFAULT_ACL_MAX_RETRY), messageReadChunkSize.orElse(DEFAULT_MESSAGE_CHUNK_SIZE_ON_READ), expungeChunkSize.orElse(DEFAULT_EXPUNGE_BATCH_SIZE), @@ -205,7 +250,9 @@ public class CassandraConfiguration { fetchNextPageInAdvanceRow.orElse(DEFAULT_FETCH_NEXT_PAGE_ADVANCE_IN_ROW), blobPartSize.orElse(DEFAULT_BLOB_PART_SIZE), attachmentV2MigrationReadTimeout.orElse(DEFAULT_ATTACHMENT_V2_MIGRATION_READ_TIMEOUT), - messageAttachmentIdsReadTimeout.orElse(DEFAULT_MESSAGE_ATTACHMENT_ID_MIGRATION_READ_TIMEOUT)); + messageAttachmentIdsReadTimeout.orElse(DEFAULT_MESSAGE_ATTACHMENT_ID_MIGRATION_READ_TIMEOUT), + consistencyLevelRegular, + consistencyLevelLightweightTransaction); } } @@ -237,6 +284,10 @@ public class CassandraConfiguration { propertiesConfiguration.getInteger(ATTACHMENT_V2_MIGRATION_READ_TIMEOUT, null))) .messageAttachmentIdsReadTimeout(Optional.ofNullable( propertiesConfiguration.getInteger(MESSAGE_ATTACHMENTID_READ_TIMEOUT, null))) + .consistencyLevelRegular(Optional.ofNullable( + propertiesConfiguration.getString(CONSISTENCY_LEVEL_REGULAR))) + .consistencyLevelLightweightTransaction(Optional.ofNullable( + propertiesConfiguration.getString(CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION))) .build(); } @@ -251,12 +302,15 @@ public class CassandraConfiguration { private final int blobPartSize; private final int attachmentV2MigrationReadTimeout; private final int messageAttachmentIdsReadTimeout; + private final String consistencyLevelRegular; + private final String consistencyLevelLightweightTransaction; @VisibleForTesting CassandraConfiguration(int aclMaxRetry, int messageReadChunkSize, int expungeChunkSize, int flagsUpdateMessageIdMaxRetry, int flagsUpdateMessageMaxRetry, int modSeqMaxRetry, int uidMaxRetry, int fetchNextPageInAdvanceRow, - int blobPartSize, final int attachmentV2MigrationReadTimeout, int messageAttachmentIdsReadTimeout) { + int blobPartSize, final int attachmentV2MigrationReadTimeout, int messageAttachmentIdsReadTimeout, + String consistencyLevelRegular, String consistencyLevelLightweightTransaction) { this.aclMaxRetry = aclMaxRetry; this.messageReadChunkSize = messageReadChunkSize; this.expungeChunkSize = expungeChunkSize; @@ -268,6 +322,8 @@ public class CassandraConfiguration { this.blobPartSize = blobPartSize; this.attachmentV2MigrationReadTimeout = attachmentV2MigrationReadTimeout; this.messageAttachmentIdsReadTimeout = messageAttachmentIdsReadTimeout; + this.consistencyLevelRegular = consistencyLevelRegular; + this.consistencyLevelLightweightTransaction = consistencyLevelLightweightTransaction; } public int getBlobPartSize() { @@ -314,6 +370,14 @@ public class CassandraConfiguration { return messageAttachmentIdsReadTimeout; } + public String getConsistencyLevelRegular() { + return consistencyLevelRegular; + } + + public String getConsistencyLevelLightweightTransaction() { + return consistencyLevelLightweightTransaction; + } + @Override public final boolean equals(Object o) { if (o instanceof CassandraConfiguration) { @@ -329,7 +393,9 @@ public class CassandraConfiguration { && Objects.equals(this.fetchNextPageInAdvanceRow, that.fetchNextPageInAdvanceRow) && Objects.equals(this.blobPartSize, that.blobPartSize) && Objects.equals(this.attachmentV2MigrationReadTimeout, that.attachmentV2MigrationReadTimeout) - && Objects.equals(this.messageAttachmentIdsReadTimeout, that.messageAttachmentIdsReadTimeout); + && Objects.equals(this.messageAttachmentIdsReadTimeout, that.messageAttachmentIdsReadTimeout) + && Objects.equals(this.consistencyLevelRegular, that.consistencyLevelRegular) + && Objects.equals(this.consistencyLevelLightweightTransaction, that.consistencyLevelLightweightTransaction); } return false; } @@ -338,7 +404,8 @@ public class CassandraConfiguration { public final int hashCode() { return Objects.hash(aclMaxRetry, messageReadChunkSize, expungeChunkSize, flagsUpdateMessageIdMaxRetry, flagsUpdateMessageMaxRetry, modSeqMaxRetry, uidMaxRetry, fetchNextPageInAdvanceRow, - blobPartSize, attachmentV2MigrationReadTimeout, messageAttachmentIdsReadTimeout); + blobPartSize, attachmentV2MigrationReadTimeout, messageAttachmentIdsReadTimeout, + consistencyLevelRegular, consistencyLevelLightweightTransaction); } @Override @@ -355,6 +422,8 @@ public class CassandraConfiguration { .add("blobPartSize", blobPartSize) .add("attachmentV2MigrationReadTimeout", attachmentV2MigrationReadTimeout) .add("messageAttachmentIdsReadTimeout", messageAttachmentIdsReadTimeout) + .add("consistencyLevelRegular", consistencyLevelRegular) + .add("consistencyLevelLightweightTransaction", consistencyLevelLightweightTransaction) .toString(); } } diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConsistenciesConfiguration.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConsistenciesConfiguration.java new file mode 100644 index 0000000..e1f71e6 --- /dev/null +++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConsistenciesConfiguration.java @@ -0,0 +1,90 @@ +/**************************************************************** + * 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.backends.cassandra.init.configuration; + +import java.util.Objects; + +import com.datastax.driver.core.ConsistencyLevel; +import com.google.common.base.MoreObjects; + +public class CassandraConsistenciesConfiguration { + public static ConsistencyLevel fromString(String value) { + switch (value) { + case "QUORUM": + return ConsistencyLevel.QUORUM; + case "LOCAL_QUORUM": + return ConsistencyLevel.LOCAL_QUORUM; + case "EACH_QUORUM": + return ConsistencyLevel.EACH_QUORUM; + case "SERIAL": + return ConsistencyLevel.SERIAL; + case "LOCAL_SERIAL": + return ConsistencyLevel.LOCAL_SERIAL; + } + throw new IllegalArgumentException("'" + value + "' is not a value ConsistencyLevel"); + } + + public static CassandraConsistenciesConfiguration fromConfiguration(CassandraConfiguration configuration) { + return new CassandraConsistenciesConfiguration( + fromString(configuration.getConsistencyLevelRegular()), + fromString(configuration.getConsistencyLevelLightweightTransaction())); + } + + private final ConsistencyLevel regular; + private final ConsistencyLevel lightweightTransaction; + + private CassandraConsistenciesConfiguration(ConsistencyLevel regular, + ConsistencyLevel lightweightTransaction) { + this.regular = regular; + this.lightweightTransaction = lightweightTransaction; + } + + public ConsistencyLevel getRegular() { + return regular; + } + + public ConsistencyLevel getLightweightTransaction() { + return lightweightTransaction; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof CassandraConsistenciesConfiguration) { + CassandraConsistenciesConfiguration that = (CassandraConsistenciesConfiguration) o; + + return Objects.equals(this.regular, that.regular) + && Objects.equals(this.lightweightTransaction, that.lightweightTransaction); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(regular, lightweightTransaction); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("consistencyLevelRegular", regular) + .add("consistencyLevelLightweightTransaction", lightweightTransaction) + .toString(); + } +} diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/CassandraConfigurationReadingTest.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/CassandraConfigurationReadingTest.java index a6f5995..cf3b28d 100644 --- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/CassandraConfigurationReadingTest.java +++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/CassandraConfigurationReadingTest.java @@ -60,6 +60,8 @@ class CassandraConfigurationReadingTest { .blobPartSize(9) .attachmentV2MigrationReadTimeout(10) .messageAttachmentIdsReadTimeout(11) + .consistencyLevelRegular("LOCAL_QUORUM") + .consistencyLevelLightweightTransaction("LOCAL_SERIAL") .build()); } diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/CassandraConfigurationTest.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/CassandraConfigurationTest.java index 678b7f7..ce9f638 100644 --- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/CassandraConfigurationTest.java +++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/CassandraConfigurationTest.java @@ -183,6 +183,20 @@ class CassandraConfigurationTest { } @Test + void consistencyLevelRegularShouldThrowOnNotSupportedValue() { + assertThatThrownBy(() -> CassandraConfiguration.builder() + .consistencyLevelRegular("ALL")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void consistencyLevelLightweightTransactionShouldThrowOnNotSupportedValue() { + assertThatThrownBy(() -> CassandraConfiguration.builder() + .consistencyLevelLightweightTransaction("ALL")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test void builderShouldCreateTheRightObject() { int aclMaxRetry = 1; int modSeqMaxRetry = 2; @@ -195,6 +209,8 @@ class CassandraConfigurationTest { int blobPartSize = 10; int attachmentV2MigrationReadTimeout = 11; int messageAttachmentIdReadTimeout = 12; + String consistencyLevelRegular = "LOCAL_QUORUM"; + String consistencyLevelLightweightTransaction = "LOCAL_SERIAL"; CassandraConfiguration configuration = CassandraConfiguration.builder() .aclMaxRetry(aclMaxRetry) @@ -208,6 +224,8 @@ class CassandraConfigurationTest { .blobPartSize(blobPartSize) .attachmentV2MigrationReadTimeout(attachmentV2MigrationReadTimeout) .messageAttachmentIdsReadTimeout(messageAttachmentIdReadTimeout) + .consistencyLevelRegular(consistencyLevelRegular) + .consistencyLevelLightweightTransaction(consistencyLevelLightweightTransaction) .build(); SoftAssertions.assertSoftly(softly -> { @@ -222,6 +240,8 @@ class CassandraConfigurationTest { softly.assertThat(configuration.getBlobPartSize()).isEqualTo(blobPartSize); softly.assertThat(configuration.getAttachmentV2MigrationReadTimeout()).isEqualTo(attachmentV2MigrationReadTimeout); softly.assertThat(configuration.getMessageAttachmentIdsReadTimeout()).isEqualTo(messageAttachmentIdReadTimeout); + softly.assertThat(configuration.getConsistencyLevelRegular()).isEqualTo(consistencyLevelRegular); + softly.assertThat(configuration.getConsistencyLevelLightweightTransaction()).isEqualTo(consistencyLevelLightweightTransaction); }); } diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/configuration/CassandraConsistenciesConfigurationTest.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/configuration/CassandraConsistenciesConfigurationTest.java new file mode 100644 index 0000000..4e282dc --- /dev/null +++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/configuration/CassandraConsistenciesConfigurationTest.java @@ -0,0 +1,84 @@ +/**************************************************************** + * 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.backends.cassandra.init.configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.stream.Stream; + +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import com.datastax.driver.core.ConsistencyLevel; +import nl.jqno.equalsverifier.EqualsVerifier; + +class CassandraConsistenciesConfigurationTest { + @Test + void cassandraConsistenciesConfigurationShouldRespectBeanContract() { + EqualsVerifier.forClass(CassandraConsistenciesConfiguration.class) + .verify(); + } + + @Test + void fromStringShouldThrowOnInvalidValue() { + assertThatThrownBy(() -> CassandraConsistenciesConfiguration.fromString("INVALID")) + .isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @MethodSource + void fromStringShouldInstantiateTheRightValue(String rawValue, ConsistencyLevel expected) { + assertThat(CassandraConsistenciesConfiguration.fromString(rawValue)) + .isEqualTo(expected); + } + + private static Stream<Arguments> fromStringShouldInstantiateTheRightValue() { + return Stream.of( + Arguments.of("QUORUM", ConsistencyLevel.QUORUM), + Arguments.of("LOCAL_QUORUM", ConsistencyLevel.LOCAL_QUORUM), + Arguments.of("EACH_QUORUM", ConsistencyLevel.EACH_QUORUM), + Arguments.of("SERIAL", ConsistencyLevel.SERIAL), + Arguments.of("LOCAL_SERIAL", ConsistencyLevel.LOCAL_SERIAL) + ); + } + + @Test + void fromConfigurationShouldTakeTheValues() { + String consistencyLevelRegular = "LOCAL_QUORUM"; + String consistencyLevelLightweightTransaction = "LOCAL_SERIAL"; + + CassandraConfiguration configuration = CassandraConfiguration.builder() + .consistencyLevelRegular(consistencyLevelRegular) + .consistencyLevelLightweightTransaction(consistencyLevelLightweightTransaction) + .build(); + + CassandraConsistenciesConfiguration consistenciesConfiguration = CassandraConsistenciesConfiguration + .fromConfiguration(configuration); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(consistenciesConfiguration.getRegular()).isEqualTo(ConsistencyLevel.LOCAL_QUORUM); + softly.assertThat(consistenciesConfiguration.getLightweightTransaction()).isEqualTo(ConsistencyLevel.LOCAL_SERIAL); + }); + } +} \ No newline at end of file diff --git a/backends-common/cassandra/src/test/resources/configuration-reader-test/cassandra.properties b/backends-common/cassandra/src/test/resources/configuration-reader-test/cassandra.properties index 27f4430..10ca4dd 100644 --- a/backends-common/cassandra/src/test/resources/configuration-reader-test/cassandra.properties +++ b/backends-common/cassandra/src/test/resources/configuration-reader-test/cassandra.properties @@ -9,3 +9,5 @@ chunk.size.expunge=8 mailbox.blob.part.size=9 attachment.v2.migration.read.timeout=10 message.attachmentids.read.timeout=11 +cassandra.consistency_level.regular=LOCAL_QUORUM +cassandra.consistency_level.lightweight_transaction=LOCAL_SERIAL \ No newline at end of file diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/conf/cassandra.properties b/dockerfiles/run/guice/cassandra-ldap/destination/conf/cassandra.properties index 0e19020..c1bbe41 100644 --- a/dockerfiles/run/guice/cassandra-ldap/destination/conf/cassandra.properties +++ b/dockerfiles/run/guice/cassandra-ldap/destination/conf/cassandra.properties @@ -23,3 +23,10 @@ cassandra.retryConnection.minDelay=5000 # chunk.size.message.read=100 # chunk.size.expunge=100 # mailbox.blob.part.size=102400 + +## Consistency levels used for common queries +## Read https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/dml/dmlConfigConsistency.html +# QUORUM, LOCAL_QUORUM, or EACH_QUORUM +# cassandra.consistency_level.regular=QUORUM +# SERIAL or LOCAL_SERIAL +# cassandra.consistency_level.lightweight_transaction=SERIAL diff --git a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/cassandra.properties b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/cassandra.properties index 137b2cc..e7dff97 100644 --- a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/cassandra.properties +++ b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/cassandra.properties @@ -33,3 +33,10 @@ cassandra.retryConnection.minDelay=5000 # chunk.size.message.read=100 # chunk.size.expunge=100 # mailbox.blob.part.size=102400 + +## Consistency levels used for common queries +## Read https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/dml/dmlConfigConsistency.html +# QUORUM, LOCAL_QUORUM, or EACH_QUORUM +# cassandra.consistency_level.regular=QUORUM +# SERIAL or LOCAL_SERIAL +# cassandra.consistency_level.lightweight_transaction=SERIAL diff --git a/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/cassandra.properties b/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/cassandra.properties index 137b2cc..e7dff97 100644 --- a/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/cassandra.properties +++ b/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/cassandra.properties @@ -33,3 +33,10 @@ cassandra.retryConnection.minDelay=5000 # chunk.size.message.read=100 # chunk.size.expunge=100 # mailbox.blob.part.size=102400 + +## Consistency levels used for common queries +## Read https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/dml/dmlConfigConsistency.html +# QUORUM, LOCAL_QUORUM, or EACH_QUORUM +# cassandra.consistency_level.regular=QUORUM +# SERIAL or LOCAL_SERIAL +# cassandra.consistency_level.lightweight_transaction=SERIAL diff --git a/dockerfiles/run/guice/cassandra/destination/conf/cassandra.properties b/dockerfiles/run/guice/cassandra/destination/conf/cassandra.properties index b96beef..1e1bae2 100644 --- a/dockerfiles/run/guice/cassandra/destination/conf/cassandra.properties +++ b/dockerfiles/run/guice/cassandra/destination/conf/cassandra.properties @@ -33,3 +33,10 @@ cassandra.retryConnection.minDelay=5000 # chunk.size.message.read=100 # chunk.size.expunge=100 # mailbox.blob.part.size=102400 + +## Consistency levels used for common queries +## Read https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/dml/dmlConfigConsistency.html +# QUORUM, LOCAL_QUORUM, or EACH_QUORUM +# cassandra.consistency_level.regular=QUORUM +# SERIAL or LOCAL_SERIAL +# cassandra.consistency_level.lightweight_transaction=SERIAL 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 d8004f2..165ce05 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 @@ -29,6 +29,7 @@ import org.apache.james.backends.cassandra.init.KeyspaceFactory; import org.apache.james.backends.cassandra.init.ResilientClusterProvider; import org.apache.james.backends.cassandra.init.SessionWithInitializedTablesFactory; import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration; +import org.apache.james.backends.cassandra.init.configuration.CassandraConsistenciesConfiguration; import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration; import org.apache.james.backends.cassandra.init.configuration.KeyspaceConfiguration; import org.apache.james.backends.cassandra.utils.CassandraHealthCheck; @@ -135,6 +136,13 @@ public class CassandraSessionModule extends AbstractModule { } } + @VisibleForTesting + @Provides + @Singleton + CassandraConsistenciesConfiguration provideCassandraConsistenciesConfiguration(CassandraConfiguration configuration) { + return CassandraConsistenciesConfiguration.fromConfiguration(configuration); + } + @Provides @Singleton ClusterConfiguration provideClusterConfiguration(PropertiesProvider propertiesProvider) throws ConfigurationException { diff --git a/src/site/xdoc/server/config-cassandra.xml b/src/site/xdoc/server/config-cassandra.xml index 34a05df..e725404 100644 --- a/src/site/xdoc/server/config-cassandra.xml +++ b/src/site/xdoc/server/config-cassandra.xml @@ -136,6 +136,12 @@ <dd>Optional. Defaults to 50.<br/> Controls the number of messages to be expunged in parallel.</dd> <dt><strong>mailbox.blob.part.size</strong></dt> <dd>Optional. Defaults to 102400 (100KB).<br/> Controls the size of blob parts used to store messages.</dd> + + <dt><strong>Allows specifying the driver default consistency level.</strong></dt> + <dt><strong>cassandra.consistency_level.regular</strong></dt> + <dd>Optional. Defaults to QUORUM.<br/> <a href="https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/dml/dmlConfigConsistency.html">QUORUM, LOCAL_QUORUM, or EACH_QUORUM</a>.</dd> + <dt><strong>cassandra.consistency_level.lightweight_transaction</strong></dt> + <dd>Optional. Defaults to SERIAL.<br/> <a href="https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/dml/dmlConfigConsistency.html">SERIAL or LOCAL_SERIAL</a>.</dd> </dl> --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org