You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2022/03/30 03:54:09 UTC

[james-project] branch master updated: JAMES-3726 Allow relaxing CassandraMailRepository LWT usage (#921)

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


The following commit(s) were added to refs/heads/master by this push:
     new 0d03016  JAMES-3726 Allow relaxing CassandraMailRepository LWT usage (#921)
0d03016 is described below

commit 0d03016773c4341a80933f5b6cce12c0516ff9e6
Author: vttran <vt...@linagora.com>
AuthorDate: Wed Mar 30 10:54:03 2022 +0700

    JAMES-3726 Allow relaxing CassandraMailRepository LWT usage (#921)
---
 .../init/configuration/CassandraConfiguration.java | 28 ++++++++--
 .../sample-configuration/cassandra.properties      |  5 ++
 .../modules/ROOT/pages/configure/cassandra.adoc    |  4 ++
 .../sample-configuration/cassandra.properties      |  5 ++
 .../sample-configuration/cassandra.properties      |  5 ++
 .../cassandra/CassandraMailRepositoryKeysDAO.java  | 27 +++++++---
 .../CassandraMailRepositoryKeysDAOTest.java        | 63 ++++++++++++++++------
 .../cassandra/CassandraMailRepositoryTest.java     | 29 +++++++++-
 ...aMailRepositoryWithFakeImplementationsTest.java |  3 +-
 src/site/xdoc/server/config-cassandra.xml          |  3 ++
 10 files changed, 143 insertions(+), 29 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 ce6b87a..75587d4 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
@@ -59,6 +59,7 @@ public class CassandraConfiguration {
     public static final List<String> VALID_CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION = ImmutableList.of("SERIAL", "LOCAL_SERIAL");
     public static final boolean DEFAULT_STRONG_CONSISTENCY = true;
     public static final boolean DEFAULT_OPTIMISTIC_CONSISTENCY_LEVEL = false;
+    public static final boolean DEFAULT_MAIL_REPOSITORY_STRONG_CONSISTENCY = true;
 
     private static final String MAILBOX_READ_REPAIR = "mailbox.read.repair.chance";
     private static final String MAILBOX_MAX_COUNTERS_READ_REPAIR = "mailbox.counters.read.repair.chance.max";
@@ -80,6 +81,7 @@ public class CassandraConfiguration {
     private static final String CONSISTENCY_LEVEL_REGULAR = "cassandra.consistency_level.regular";
     private static final String CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION = "cassandra.consistency_level.lightweight_transaction";
     private static final String OPTIMISTIC_CONSISTENCY_LEVEL = "optimistic.consistency.level.enabled";
+    private static final String MAIL_REPOSITORY_STRONG_CONSISTENCY = "mailrepository.strong.consistency";
 
     public static final CassandraConfiguration DEFAULT_CONFIGURATION = builder().build();
 
@@ -104,6 +106,7 @@ public class CassandraConfiguration {
         private Optional<Boolean> messageReadStrongConsistency = Optional.empty();
         private Optional<Boolean> messageWriteStrongConsistency = Optional.empty();
         private Optional<Boolean> optimisticConsistencyLevel = Optional.empty();
+        private Optional<Boolean> mailRepositoryStrongConsistency = Optional.empty();
 
         public Builder mailboxReadStrongConsistency(boolean value) {
             this.mailboxReadStrongConsistency = Optional.of(value);
@@ -326,6 +329,11 @@ public class CassandraConfiguration {
             return this;
         }
 
+        public Builder mailRepositoryStrongConsistency(Optional<Boolean> value) {
+            this.mailRepositoryStrongConsistency = value;
+            return this;
+        }
+
         public CassandraConfiguration build() {
             String consistencyLevelRegular = this.consistencyLevelRegular.orElse(DEFAULT_CONSISTENCY_LEVEL_REGULAR);
             String consistencyLevelLightweightTransaction = this.consistencyLevelLightweightTransaction.orElse(DEFAULT_CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION);
@@ -354,7 +362,8 @@ public class CassandraConfiguration {
                 mailboxReadStrongConsistency.orElse(DEFAULT_STRONG_CONSISTENCY),
                 messageReadStrongConsistency.orElse(DEFAULT_STRONG_CONSISTENCY),
                 messageWriteStrongConsistency.orElse(DEFAULT_STRONG_CONSISTENCY),
-                optimisticConsistencyLevel.orElse(DEFAULT_OPTIMISTIC_CONSISTENCY_LEVEL));
+                optimisticConsistencyLevel.orElse(DEFAULT_OPTIMISTIC_CONSISTENCY_LEVEL),
+                mailRepositoryStrongConsistency.orElse(DEFAULT_MAIL_REPOSITORY_STRONG_CONSISTENCY));
         }
     }
 
@@ -404,6 +413,8 @@ public class CassandraConfiguration {
                 propertiesConfiguration.getBoolean(MESSAGE_WRITE_STRONG_CONSISTENCY, null)))
             .optimisticConsistencyLevel(Optional.ofNullable(
                 propertiesConfiguration.getBoolean(OPTIMISTIC_CONSISTENCY_LEVEL, null)))
+            .mailRepositoryStrongConsistency(Optional.ofNullable(
+                propertiesConfiguration.getBoolean(MAIL_REPOSITORY_STRONG_CONSISTENCY, null)))
             .build();
     }
 
@@ -427,6 +438,7 @@ public class CassandraConfiguration {
     private final boolean messageReadStrongConsistency;
     private final boolean messageWriteStrongConsistency;
     private final boolean optimisticConsistencyLevel;
+    private final boolean mailRepositoryStrongConsistency;
 
     @VisibleForTesting
     CassandraConfiguration(int aclMaxRetry, int messageReadChunkSize, int expungeChunkSize,
@@ -437,7 +449,7 @@ public class CassandraConfiguration {
                            float mailboxReadRepair, float mailboxCountersReadRepairChanceMax,
                            float mailboxCountersReadRepairChanceOneHundred, boolean mailboxReadStrongConsistency,
                            boolean messageReadStrongConsistency, boolean messageWriteStrongConsistency,
-                           boolean optimisticConsistencyLevel) {
+                           boolean optimisticConsistencyLevel, boolean mailRepositoryStrongConsistency) {
         this.aclMaxRetry = aclMaxRetry;
         this.messageReadChunkSize = messageReadChunkSize;
         this.expungeChunkSize = expungeChunkSize;
@@ -458,6 +470,7 @@ public class CassandraConfiguration {
         this.messageReadStrongConsistency = messageReadStrongConsistency;
         this.messageWriteStrongConsistency = messageWriteStrongConsistency;
         this.optimisticConsistencyLevel = optimisticConsistencyLevel;
+        this.mailRepositoryStrongConsistency = mailRepositoryStrongConsistency;
     }
 
     public boolean isMailboxReadStrongConsistency() {
@@ -540,6 +553,10 @@ public class CassandraConfiguration {
         return optimisticConsistencyLevel;
     }
 
+    public boolean isMailRepositoryStrongConsistency() {
+        return mailRepositoryStrongConsistency;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof CassandraConfiguration) {
@@ -564,7 +581,9 @@ public class CassandraConfiguration {
                 && Objects.equals(this.messageWriteStrongConsistency, that.messageWriteStrongConsistency)
                 && Objects.equals(this.consistencyLevelRegular, that.consistencyLevelRegular)
                 && Objects.equals(this.consistencyLevelLightweightTransaction, that.consistencyLevelLightweightTransaction)
-                && Objects.equals(this.optimisticConsistencyLevel, that.optimisticConsistencyLevel);
+                && Objects.equals(this.optimisticConsistencyLevel, that.optimisticConsistencyLevel)
+                && Objects.equals(this.mailRepositoryStrongConsistency, that.mailRepositoryStrongConsistency);
+
         }
         return false;
     }
@@ -577,7 +596,7 @@ public class CassandraConfiguration {
             blobPartSize, attachmentV2MigrationReadTimeout, messageAttachmentIdsReadTimeout,
             consistencyLevelRegular, consistencyLevelLightweightTransaction, mailboxReadRepair,
             messageReadStrongConsistency, mailboxReadStrongConsistency, messageWriteStrongConsistency,
-            optimisticConsistencyLevel);
+            optimisticConsistencyLevel, mailRepositoryStrongConsistency);
     }
 
     @Override
@@ -603,6 +622,7 @@ public class CassandraConfiguration {
             .add("consistencyLevelRegular", consistencyLevelRegular)
             .add("consistencyLevelLightweightTransaction", consistencyLevelLightweightTransaction)
             .add("optimisticConsistencyLevel", optimisticConsistencyLevel)
+            .add("mailRepositoryStrongConsistency", mailRepositoryStrongConsistency)
             .toString();
     }
 }
diff --git a/server/apps/cassandra-app/sample-configuration/cassandra.properties b/server/apps/cassandra-app/sample-configuration/cassandra.properties
index a8ece8e..6728bef 100644
--- a/server/apps/cassandra-app/sample-configuration/cassandra.properties
+++ b/server/apps/cassandra-app/sample-configuration/cassandra.properties
@@ -52,3 +52,8 @@ cassandra.retryConnection.minDelay=5000
 # Falls back to default read consistency level if the blob is missing.
 # Defaults to false.
 # optimistic.consistency.level.enabled=false
+
+# Optional. Allows not to use lightweight transactions in CassandraMailRepository.
+# If disabled we implement an idempotent behaviour (duplicates are overridden, missing entries upon deletes are ignored).
+# Defaults to true.
+# mailrepository.strong.consistency=true
\ No newline at end of file
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/cassandra.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/cassandra.adoc
index 8ec1c79..408c41e 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/cassandra.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/cassandra.adoc
@@ -215,4 +215,8 @@ If disabled, Lightweight transactions will no longer be used upon messages opera
 As message flags updates relies so far on a read-before-write model, it exposes yourself to data races leading to
 potentially update loss. Better performance are expected
 by turning it off. Reads performed as part of write transaction are also performed with a relaxed consistency.
+
+| mailrepository.strong.consistency
+| Optional. Boolean, defaults to true. Allows not to use lightweight transactions in CassandraMailRepository.
+| If disabled we implement an idempotent behaviour (duplicates are overridden, missing entries upon deletes are ignored).
 |===
\ No newline at end of file
diff --git a/server/apps/distributed-app/sample-configuration/cassandra.properties b/server/apps/distributed-app/sample-configuration/cassandra.properties
index c915e21..88df52b 100644
--- a/server/apps/distributed-app/sample-configuration/cassandra.properties
+++ b/server/apps/distributed-app/sample-configuration/cassandra.properties
@@ -52,3 +52,8 @@ cassandra.retryConnection.minDelay=5000
 # Falls back to default read consistency level if the blob is missing.
 # Defaults to false.
 # optimistic.consistency.level.enabled=false
+
+# Optional. Allows not to use lightweight transactions in CassandraMailRepository.
+# If disabled we implement an idempotent behaviour (duplicates are overridden, missing entries upon deletes are ignored).
+# Defaults to true.
+# mailrepository.strong.consistency=true
\ No newline at end of file
diff --git a/server/apps/distributed-pop3-app/sample-configuration/cassandra.properties b/server/apps/distributed-pop3-app/sample-configuration/cassandra.properties
index c915e21..b6394ff 100644
--- a/server/apps/distributed-pop3-app/sample-configuration/cassandra.properties
+++ b/server/apps/distributed-pop3-app/sample-configuration/cassandra.properties
@@ -52,3 +52,8 @@ cassandra.retryConnection.minDelay=5000
 # Falls back to default read consistency level if the blob is missing.
 # Defaults to false.
 # optimistic.consistency.level.enabled=false
+
+# Optional. Allows not to use lightweight transactions in CassandraMailRepository.
+# If disabled we implement an idempotent behaviour (duplicates are overridden, missing entries upon deletes are ignored).
+# Defaults to true.
+# mailrepository.strong.consistency=true
diff --git a/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryKeysDAO.java b/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryKeysDAO.java
index 7bbc3c9..a9f7fdb 100644
--- a/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryKeysDAO.java
+++ b/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryKeysDAO.java
@@ -30,12 +30,15 @@ import static org.apache.james.mailrepository.cassandra.MailRepositoryTable.REPO
 
 import javax.inject.Inject;
 
+import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
 import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
 
 import com.datastax.driver.core.PreparedStatement;
 import com.datastax.driver.core.Session;
+import com.datastax.driver.core.querybuilder.Delete;
+import com.datastax.driver.core.querybuilder.Insert;
 
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
@@ -46,9 +49,11 @@ public class CassandraMailRepositoryKeysDAO {
     private final PreparedStatement insertKey;
     private final PreparedStatement deleteKey;
     private final PreparedStatement listKeys;
+    private final boolean strongConsistency;
 
     @Inject
-    public CassandraMailRepositoryKeysDAO(Session session) {
+    public CassandraMailRepositoryKeysDAO(Session session, CassandraConfiguration cassandraConfiguration) {
+        this.strongConsistency = cassandraConfiguration.isMailRepositoryStrongConsistency();
         this.executor = new CassandraAsyncExecutor(session);
 
         this.insertKey = prepareInsert(session);
@@ -63,18 +68,26 @@ public class CassandraMailRepositoryKeysDAO {
     }
 
     private PreparedStatement prepareDelete(Session session) {
-        return session.prepare(delete()
+        Delete.Where deleteStatement = delete()
             .from(KEYS_TABLE_NAME)
-            .ifExists()
             .where(eq(REPOSITORY_NAME, bindMarker(REPOSITORY_NAME)))
-            .and(eq(MAIL_KEY, bindMarker(MAIL_KEY))));
+            .and(eq(MAIL_KEY, bindMarker(MAIL_KEY)));
+
+        if (strongConsistency) {
+            return session.prepare(deleteStatement.ifExists());
+        }
+        return session.prepare(deleteStatement);
     }
 
     private PreparedStatement prepareInsert(Session session) {
-        return session.prepare(insertInto(KEYS_TABLE_NAME)
-            .ifNotExists()
+        Insert insertStatement = insertInto(KEYS_TABLE_NAME)
             .value(REPOSITORY_NAME, bindMarker(REPOSITORY_NAME))
-            .value(MAIL_KEY, bindMarker(MAIL_KEY)));
+            .value(MAIL_KEY, bindMarker(MAIL_KEY));
+
+        if (strongConsistency) {
+            return session.prepare(insertStatement.ifNotExists());
+        }
+        return session.prepare(insertStatement);
     }
 
     public Mono<Boolean> store(MailRepositoryUrl url, MailKey key) {
diff --git a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryKeysDAOTest.java b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryKeysDAOTest.java
index 0a2d568..8cec780 100644
--- a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryKeysDAOTest.java
+++ b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryKeysDAOTest.java
@@ -21,13 +21,17 @@ package org.apache.james.mailrepository.cassandra;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+import java.util.Optional;
+
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
@@ -47,7 +51,7 @@ class CassandraMailRepositoryKeysDAOTest {
 
     @BeforeEach
     void setUp(CassandraCluster cassandra) {
-        testee = new CassandraMailRepositoryKeysDAO(cassandra.getConf());
+        testee = new CassandraMailRepositoryKeysDAO(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION);
     }
 
     @Test
@@ -119,27 +123,56 @@ class CassandraMailRepositoryKeysDAOTest {
     }
 
     @Test
-    void removeShouldReturnFalseWhenKeyNotDeleted() {
-        boolean isDeleted = testee.remove(URL2, KEY_2).block();
-
-        assertThat(isDeleted).isFalse();
-    }
-
-
-    @Test
     void storeShouldReturnTrueWhenNotPreviouslyStored() {
         boolean isStored = testee.store(URL, KEY_1).block();
 
         assertThat(isStored).isTrue();
     }
 
-    @Test
-    void storeShouldReturnFalseWhenPreviouslyStored() {
-        testee.store(URL, KEY_1).block();
-
-        boolean isStored = testee.store(URL, KEY_1).block();
+    @Nested
+    class WhenStrongConsistencyIsFalse {
+        CassandraMailRepositoryKeysDAO testee;
+
+        @BeforeEach
+        void setUp(CassandraCluster cassandra) {
+            testee = new CassandraMailRepositoryKeysDAO(cassandra.getConf(), CassandraConfiguration.builder()
+                .mailRepositoryStrongConsistency(Optional.of(false))
+                .build());
+        }
+
+        @Test
+        void storeShouldReturnTrueWhenPreviouslyStored() {
+            testee.store(URL, KEY_1).block();
+            assertThat(testee.store(URL, KEY_1).block()).isTrue();
+        }
+
+        @Test
+        void removeShouldReturnTrueWhenKeyNotDeleted() {
+            assertThat(testee.remove(URL2, KEY_2).block()).isTrue();
+        }
+    }
 
-        assertThat(isStored).isFalse();
+    @Nested
+    class WhenStrongConsistencyIsTrue {
+        CassandraMailRepositoryKeysDAO testee;
+
+        @BeforeEach
+        void setUp(CassandraCluster cassandra) {
+            testee = new CassandraMailRepositoryKeysDAO(cassandra.getConf(), CassandraConfiguration.builder()
+                .mailRepositoryStrongConsistency(Optional.of(true))
+                .build());
+        }
+
+        @Test
+        void storeShouldReturnFalseWhenPreviouslyStored() {
+            testee.store(URL, KEY_1).block();
+            assertThat(testee.store(URL, KEY_1).block()).isFalse();
+        }
+
+        @Test
+        void removeShouldReturnFalseWhenKeyNotDeleted() {
+            assertThat(testee.remove(URL2, KEY_2).block()).isFalse();
+        }
     }
 
 }
\ No newline at end of file
diff --git a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryTest.java b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryTest.java
index 3abea42..10a3c03 100644
--- a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryTest.java
+++ b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryTest.java
@@ -26,6 +26,7 @@ import static org.assertj.core.api.Assertions.assertThatCode;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.HashBlobId;
@@ -62,7 +63,7 @@ class CassandraMailRepositoryTest {
         @BeforeEach
         void setup(CassandraCluster cassandra) {
             CassandraMailRepositoryMailDaoV2 v2 = new CassandraMailRepositoryMailDaoV2(cassandra.getConf(), BLOB_ID_FACTORY);
-            CassandraMailRepositoryKeysDAO keysDAO = new CassandraMailRepositoryKeysDAO(cassandra.getConf());
+            CassandraMailRepositoryKeysDAO keysDAO = new CassandraMailRepositoryKeysDAO(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION);
             CassandraMailRepositoryCountDAO countDAO = new CassandraMailRepositoryCountDAO(cassandra.getConf());
             BlobStore blobStore = CassandraBlobStoreFactory.forTesting(cassandra.getConf(), new RecordingMetricFactory())
                 .passthrough();
@@ -83,6 +84,18 @@ class CassandraMailRepositoryTest {
         }
 
         @Test
+        @Disabled("depend on setting turn on/off lightweight transaction")
+        @Override
+        public void storeShouldHaveNoEffectOnSizeWhenAlreadyStoredMail() {
+        }
+
+        @Test
+        @Disabled("depend on setting turn on/off lightweight transaction")
+        @Override
+        public void removeShouldHaveNoEffectOnSizeWhenUnknownKeys() {
+        }
+
+        @Test
         void removeShouldDeleteStoredBlobs(CassandraCluster cassandra) throws Exception {
             MailRepository testee = retrieveRepository();
 
@@ -100,7 +113,7 @@ class CassandraMailRepositoryTest {
         @BeforeEach
         void setup(CassandraCluster cassandra) {
             CassandraMailRepositoryMailDaoV2 v2 = new CassandraMailRepositoryMailDaoV2(cassandra.getConf(), BLOB_ID_FACTORY);
-            CassandraMailRepositoryKeysDAO keysDAO = new CassandraMailRepositoryKeysDAO(cassandra.getConf());
+            CassandraMailRepositoryKeysDAO keysDAO = new CassandraMailRepositoryKeysDAO(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION);
             CassandraMailRepositoryCountDAO countDAO = new CassandraMailRepositoryCountDAO(cassandra.getConf());
             BlobStore blobStore = CassandraBlobStoreFactory.forTesting(cassandra.getConf(), new RecordingMetricFactory())
                 .deduplication();
@@ -121,6 +134,18 @@ class CassandraMailRepositoryTest {
         }
 
         @Test
+        @Disabled("depend on setting turn on/off lightweight transaction")
+        @Override
+        public void storeShouldHaveNoEffectOnSizeWhenAlreadyStoredMail() {
+        }
+
+        @Test
+        @Disabled("depend on setting turn on/off lightweight transaction")
+        @Override
+        public void removeShouldHaveNoEffectOnSizeWhenUnknownKeys() {
+        }
+
+        @Test
         void removeShouldNotAffectMailsWithTheSameContent() throws Exception {
             MailRepository testee = retrieveRepository();
 
diff --git a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryWithFakeImplementationsTest.java b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryWithFakeImplementationsTest.java
index d931e55..714da2d 100644
--- a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryWithFakeImplementationsTest.java
+++ b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryWithFakeImplementationsTest.java
@@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.HashBlobId;
@@ -64,7 +65,7 @@ class CassandraMailRepositoryWithFakeImplementationsTest {
     @BeforeEach
     void setup(CassandraCluster cassandra) {
         CassandraMailRepositoryMailDaoV2 mailDAO = new CassandraMailRepositoryMailDaoV2(cassandra.getConf(), BLOB_ID_FACTORY);
-        keysDAO = new CassandraMailRepositoryKeysDAO(cassandra.getConf());
+        keysDAO = new CassandraMailRepositoryKeysDAO(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION);
         countDAO = new CassandraMailRepositoryCountDAO(cassandra.getConf());
         BlobStore blobStore = CassandraBlobStoreFactory.forTesting(cassandra.getConf(), new RecordingMetricFactory())
             .passthrough();
diff --git a/src/site/xdoc/server/config-cassandra.xml b/src/site/xdoc/server/config-cassandra.xml
index 8ebaf09..0ead8e6 100644
--- a/src/site/xdoc/server/config-cassandra.xml
+++ b/src/site/xdoc/server/config-cassandra.xml
@@ -183,6 +183,9 @@
         <dt><strong>optimistic.consistency.level.enabled</strong></dt>
         <dd>Optional. Defaults to false. Allows specifying consistency level ONE for reads in Cassandra BlobStore.
             Falls back to default read consistency level if the blob is missing.</dd>
+        <dt><strong>mailrepository.strong.consistency</strong></dt>
+        <dd>Optional. Defaults to true. Allows not to use lightweight transactions in CassandraMailRepository.
+            If disabled we implement an idempotent behaviour (duplicates are overridden, missing entries upon deletes are ignored).</dd>
       </dl>
 
 

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org