You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2020/07/23 07:53:27 UTC

[james-project] 16/18: JAMES-3313 CassandraBlobStore should use DeDuplicatingBlobStore

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 c18ddb062a90ca51c8823931512fe4ac6e780811
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Jul 17 17:28:02 2020 +0700

    JAMES-3313 CassandraBlobStore should use DeDuplicatingBlobStore
---
 .../mail/CassandraAnnotationMapperTest.java        |   6 +-
 .../CassandraMailboxMapperConcurrencyTest.java     |   2 +
 .../mail/CassandraMailboxMapperGenericTest.java    |   2 +
 .../cassandra/mail/CassandraMessageDAOTest.java    |   5 +-
 .../mailbox/cassandra/mail/utils/GuiceUtils.java   |  22 +---
 .../quota/CassandraPerUserMaxQuotaManagerTest.java |   6 +-
 server/blob/blob-cassandra/pom.xml                 |   4 +
 .../james/blob/cassandra/CassandraBlobStore.java   | 137 ---------------------
 .../blob/cassandra/CassandraBlobStoreFactory.java} |  32 +++--
 .../blob/cassandra/CassandraDumbBlobStore.java     |   4 +-
 .../blob/cassandra/CassandraBlobStoreTest.java     |   2 +-
 .../blob/cassandra/cache/CachedBlobStoreTest.java  |   4 +-
 .../CassandraBlobStoreDependenciesModule.java      |   7 +-
 .../modules/mailbox/CassandraBlobStoreModule.java  |  11 +-
 .../modules/blobstore/BlobStoreModulesChooser.java |   5 +-
 .../cassandra/CassandraMailRepositoryTest.java     |   5 +-
 ...aMailRepositoryWithFakeImplementationsTest.java |   7 +-
 .../RabbitMQMailQueueConfigurationChangeTest.java  |   7 +-
 .../queue/rabbitmq/RabbitMQMailQueueTest.java      |   6 +-
 19 files changed, 80 insertions(+), 194 deletions(-)

diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapperTest.java
index deb914c..93d5c8a 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAnnotationMapperTest.java
@@ -20,6 +20,8 @@
 package org.apache.james.mailbox.cassandra.mail;
 
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.mail.utils.GuiceUtils;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
@@ -31,7 +33,9 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 class CassandraAnnotationMapperTest extends AnnotationMapperTest {
 
     @RegisterExtension
-    static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(CassandraAnnotationModule.MODULE);
+    static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(CassandraModule.aggregateModules(
+        CassandraBlobModule.MODULE,
+        CassandraAnnotationModule.MODULE));
 
     @Override
     protected AnnotationMapper createAnnotationMapper() {
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java
index 313fdc2..70fc8b0 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java
@@ -28,6 +28,7 @@ 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.versions.CassandraSchemaVersionModule;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.core.Username;
 import org.apache.james.mailbox.cassandra.mail.utils.GuiceUtils;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
@@ -50,6 +51,7 @@ class CassandraMailboxMapperConcurrencyTest {
     @RegisterExtension
     static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(
         CassandraModule.aggregateModules(
+            CassandraBlobModule.MODULE,
             CassandraSchemaVersionModule.MODULE,
             CassandraMailboxModule.MODULE,
             CassandraAclModule.MODULE));
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperGenericTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperGenericTest.java
index 87c6fc3..673db45 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperGenericTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperGenericTest.java
@@ -24,6 +24,7 @@ import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.mail.utils.GuiceUtils;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
@@ -38,6 +39,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraMailboxMapperGenericTest {
     private static final CassandraModule MODULES = CassandraModule.aggregateModules(
+        CassandraBlobModule.MODULE,
         CassandraSchemaVersionModule.MODULE,
         CassandraAclModule.MODULE,
         CassandraMailboxModule.MODULE,
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
index 06223e0..a58595c 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAOTest.java
@@ -34,9 +34,10 @@ 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.versions.CassandraSchemaVersionModule;
+import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
-import org.apache.james.blob.cassandra.CassandraBlobStore;
+import org.apache.james.blob.cassandra.CassandraBlobStoreFactory;
 import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.ModSeq;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
@@ -85,7 +86,7 @@ class CassandraMessageDAOTest {
     void setUp(CassandraCluster cassandra) {
         messageIdFactory = new CassandraMessageId.Factory();
         messageId = messageIdFactory.generate();
-        CassandraBlobStore blobStore = CassandraBlobStore.forTesting(cassandra.getConf());
+        BlobStore blobStore = CassandraBlobStoreFactory.forTesting(cassandra.getConf());
         HashBlobId.Factory blobIdFactory = new HashBlobId.Factory();
         testee = new CassandraMessageDAO(
             cassandra.getConf(),
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/GuiceUtils.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/GuiceUtils.java
index 02fc9dc..204438c 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/GuiceUtils.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/GuiceUtils.java
@@ -19,18 +19,14 @@
 
 package org.apache.james.mailbox.cassandra.mail.utils;
 
-import static com.google.inject.Scopes.SINGLETON;
-
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConsistenciesConfiguration;
 import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.api.BlobStore;
-import org.apache.james.blob.api.BucketName;
 import org.apache.james.blob.api.HashBlobId;
-import org.apache.james.blob.cassandra.CassandraBlobStore;
-import org.apache.james.blob.cassandra.CassandraDumbBlobStore;
+import org.apache.james.blob.cassandra.CassandraBlobStoreFactory;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.model.MessageId;
 
@@ -38,7 +34,6 @@ import com.datastax.driver.core.Session;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Module;
-import com.google.inject.name.Names;
 import com.google.inject.util.Modules;
 
 public class GuiceUtils {
@@ -53,15 +48,6 @@ public class GuiceUtils {
 
     public static Injector testInjector(Session session, CassandraTypesProvider typesProvider,
                                         CassandraMessageId.Factory messageIdFactory,
-                                        CassandraConfiguration configuration, Module... guiceModules) {
-        return Guice.createInjector(
-            Modules.combine(
-                Modules.combine(commonModules(session, typesProvider, messageIdFactory, configuration)),
-                Modules.combine(guiceModules)));
-    }
-
-    public static Injector testInjector(Session session, CassandraTypesProvider typesProvider,
-                                        CassandraMessageId.Factory messageIdFactory,
                                         CassandraConfiguration configuration) {
         return Guice.createInjector(
             commonModules(session, typesProvider, messageIdFactory, configuration));
@@ -73,11 +59,7 @@ public class GuiceUtils {
         return Modules.combine(
             binder -> binder.bind(MessageId.Factory.class).toInstance(messageIdFactory),
             binder -> binder.bind(BlobId.Factory.class).toInstance(new HashBlobId.Factory()),
-            binder -> binder.bind(BlobStore.class).to(CassandraBlobStore.class),
-            binder -> binder.bind(CassandraDumbBlobStore.class).in(SINGLETON),
-            binder -> binder.bind(BucketName.class)
-                .annotatedWith(Names.named(CassandraDumbBlobStore.DEFAULT_BUCKET))
-                .toInstance(BucketName.DEFAULT),
+            binder -> binder.bind(BlobStore.class).toInstance(CassandraBlobStoreFactory.forTesting(session)),
             binder -> binder.bind(Session.class).toInstance(session),
             binder -> binder.bind(CassandraTypesProvider.class).toInstance(typesProvider),
             binder -> binder.bind(CassandraConfiguration.class).toInstance(configuration),
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerTest.java
index c4db9d5..b1117a0 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerTest.java
@@ -20,6 +20,8 @@
 package org.apache.james.mailbox.cassandra.quota;
 
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
 import org.apache.james.mailbox.cassandra.mail.utils.GuiceUtils;
 import org.apache.james.mailbox.cassandra.modules.CassandraQuotaModule;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
@@ -29,7 +31,9 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 class CassandraPerUserMaxQuotaManagerTest extends GenericMaxQuotaManagerTest {
 
     @RegisterExtension
-    static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(CassandraQuotaModule.MODULE);
+    static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(CassandraModule.aggregateModules(
+        CassandraBlobModule.MODULE,
+        CassandraQuotaModule.MODULE));
 
     @Override
     protected MaxQuotaManager provideMaxQuotaManager() {
diff --git a/server/blob/blob-cassandra/pom.xml b/server/blob/blob-cassandra/pom.xml
index a59db28..733596a 100644
--- a/server/blob/blob-cassandra/pom.xml
+++ b/server/blob/blob-cassandra/pom.xml
@@ -55,6 +55,10 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>blob-deduplicating</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>metrics-tests</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobStore.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobStore.java
deleted file mode 100644
index b59139a..0000000
--- a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobStore.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/****************************************************************
- * 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.blob.cassandra;
-
-import java.io.InputStream;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
-import org.apache.james.blob.api.BlobId;
-import org.apache.james.blob.api.BlobStore;
-import org.apache.james.blob.api.BucketName;
-import org.apache.james.blob.api.HashBlobId;
-
-import com.datastax.driver.core.Session;
-import com.github.fge.lambdas.Throwing;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.hash.Hashing;
-import com.google.common.hash.HashingInputStream;
-import com.google.common.io.FileBackedOutputStream;
-
-import reactor.core.publisher.Mono;
-import reactor.util.function.Tuples;
-
-public class CassandraBlobStore implements BlobStore {
-
-    public static final boolean LAZY_RESOURCE_CLEANUP = false;
-    public static final int FILE_THRESHOLD = 10000;
-    private final HashBlobId.Factory blobIdFactory;
-    private final BucketName defaultBucketName;
-    private final CassandraDumbBlobStore dumbBlobStore;
-
-    @Inject
-    CassandraBlobStore(HashBlobId.Factory blobIdFactory,
-                       @Named(CassandraDumbBlobStore.DEFAULT_BUCKET) BucketName defaultBucketName,
-                       CassandraDumbBlobStore dumbBlobStore) {
-
-        this.blobIdFactory = blobIdFactory;
-        this.defaultBucketName = defaultBucketName;
-        this.dumbBlobStore = dumbBlobStore;
-    }
-
-    @VisibleForTesting
-    public static CassandraBlobStore forTesting(Session session) {
-        HashBlobId.Factory blobIdFactory = new HashBlobId.Factory();
-        CassandraBucketDAO bucketDAO = new CassandraBucketDAO(blobIdFactory, session);
-        CassandraDefaultBucketDAO defaultBucketDAO = new CassandraDefaultBucketDAO(session);
-        return new CassandraBlobStore(
-            blobIdFactory,
-            BucketName.DEFAULT,
-            new CassandraDumbBlobStore(defaultBucketDAO, bucketDAO, CassandraConfiguration.DEFAULT_CONFIGURATION, BucketName.DEFAULT));
-    }
-
-    @Override
-    public Mono<BlobId> save(BucketName bucketName, byte[] data, StoragePolicy storagePolicy) {
-        Preconditions.checkNotNull(bucketName);
-        Preconditions.checkNotNull(data);
-
-        BlobId blobId = blobIdFactory.forPayload(data);
-
-        return dumbBlobStore.save(bucketName, blobId, data)
-            .then(Mono.just(blobId));
-    }
-
-    @Override
-    public Mono<BlobId> save(BucketName bucketName, InputStream data, StoragePolicy storagePolicy) {
-        Preconditions.checkNotNull(bucketName);
-        Preconditions.checkNotNull(data);
-        HashingInputStream hashingInputStream = new HashingInputStream(Hashing.sha256(), data);
-        return Mono.using(
-            () -> new FileBackedOutputStream(FILE_THRESHOLD),
-            fileBackedOutputStream -> saveAndGenerateBlobId(bucketName, hashingInputStream, fileBackedOutputStream),
-            Throwing.consumer(FileBackedOutputStream::reset).sneakyThrow(),
-            LAZY_RESOURCE_CLEANUP);
-    }
-
-    private Mono<BlobId> saveAndGenerateBlobId(BucketName bucketName, HashingInputStream hashingInputStream, FileBackedOutputStream fileBackedOutputStream) {
-        return Mono.fromCallable(() -> {
-            IOUtils.copy(hashingInputStream, fileBackedOutputStream);
-            return Tuples.of(blobIdFactory.from(hashingInputStream.hash().toString()), fileBackedOutputStream.asByteSource());
-        })
-            .flatMap(tuple -> dumbBlobStore.save(bucketName, tuple.getT1(), tuple.getT2()).thenReturn(tuple.getT1()));
-    }
-
-    @Override
-    public Mono<byte[]> readBytes(BucketName bucketName, BlobId blobId) {
-        Preconditions.checkNotNull(bucketName);
-        return dumbBlobStore.readBytes(bucketName, blobId);
-    }
-
-    @Override
-    public InputStream read(BucketName bucketName, BlobId blobId) {
-        Preconditions.checkNotNull(bucketName);
-        return dumbBlobStore.read(bucketName, blobId);
-    }
-
-    @Override
-    public Mono<Void> deleteBucket(BucketName bucketName) {
-        Preconditions.checkNotNull(bucketName);
-
-        return dumbBlobStore.deleteBucket(bucketName);
-    }
-
-    @Override
-    public BucketName getDefaultBucketName() {
-        return defaultBucketName;
-    }
-
-    @Override
-    public Mono<Void> delete(BucketName bucketName, BlobId blobId) {
-        Preconditions.checkNotNull(bucketName);
-        Preconditions.checkNotNull(blobId);
-
-        return dumbBlobStore.delete(bucketName, blobId);
-    }
-
-}
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreModule.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobStoreFactory.java
similarity index 51%
copy from server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreModule.java
copy to server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobStoreFactory.java
index b4b3dca..cc51047 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreModule.java
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobStoreFactory.java
@@ -17,20 +17,30 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.modules.mailbox;
+package org.apache.james.blob.cassandra;
 
+import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.blob.api.BlobStore;
-import org.apache.james.blob.api.MetricableBlobStore;
-import org.apache.james.blob.cassandra.CassandraBlobStore;
+import org.apache.james.blob.api.BucketName;
+import org.apache.james.blob.api.HashBlobId;
+import org.apache.james.server.blob.deduplication.DeDuplicationBlobStore;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.name.Names;
+import com.datastax.driver.core.Session;
 
-public class CassandraBlobStoreModule extends AbstractModule {
-    @Override
-    protected void configure() {
-        bind(BlobStore.class)
-            .annotatedWith(Names.named(MetricableBlobStore.BLOB_STORE_IMPLEMENTATION))
-            .to(CassandraBlobStore.class);
+public class CassandraBlobStoreFactory {
+    public static BlobStore forTesting(HashBlobId.Factory blobIdFactory,
+                       BucketName defaultBucketName,
+                       CassandraDumbBlobStore dumbBlobStore) {
+        return new DeDuplicationBlobStore(dumbBlobStore, defaultBucketName, blobIdFactory);
+    }
+
+    public static BlobStore forTesting(Session session) {
+        HashBlobId.Factory blobIdFactory = new HashBlobId.Factory();
+        CassandraBucketDAO bucketDAO = new CassandraBucketDAO(blobIdFactory, session);
+        CassandraDefaultBucketDAO defaultBucketDAO = new CassandraDefaultBucketDAO(session);
+        return forTesting(
+            blobIdFactory,
+            BucketName.DEFAULT,
+            new CassandraDumbBlobStore(defaultBucketDAO, bucketDAO, CassandraConfiguration.DEFAULT_CONFIGURATION, BucketName.DEFAULT));
     }
 }
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraDumbBlobStore.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraDumbBlobStore.java
index b6b7ace..69dbf41 100644
--- a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraDumbBlobStore.java
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraDumbBlobStore.java
@@ -46,8 +46,6 @@ import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
 public class CassandraDumbBlobStore implements DumbBlobStore {
-
-    public static final String DEFAULT_BUCKET = "cassandraDefault";
     public static final boolean LAZY = false;
 
     private final CassandraDefaultBucketDAO defaultBucketDAO;
@@ -61,7 +59,7 @@ public class CassandraDumbBlobStore implements DumbBlobStore {
     public CassandraDumbBlobStore(CassandraDefaultBucketDAO defaultBucketDAO,
                                   CassandraBucketDAO bucketDAO,
                                   CassandraConfiguration cassandraConfiguration,
-                                  @Named(DEFAULT_BUCKET) BucketName defaultBucket) {
+                                  @Named("defaultBucket") BucketName defaultBucket) {
         this.defaultBucketDAO = defaultBucketDAO;
         this.bucketDAO = bucketDAO;
         this.configuration = cassandraConfiguration;
diff --git a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobStoreTest.java b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobStoreTest.java
index f924cfe..cf43ad5 100644
--- a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobStoreTest.java
+++ b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobStoreTest.java
@@ -71,7 +71,7 @@ public class CassandraBlobStoreTest implements MetricableBlobStoreContract {
             .build();
         testee = new MetricableBlobStore(
             metricsTestExtension.getMetricFactory(),
-            new CassandraBlobStore(
+            CassandraBlobStoreFactory.forTesting(
                 blobIdFactory,
                 BucketName.DEFAULT,
                 new CassandraDumbBlobStore(defaultBucketDAO, bucketDAO, cassandraConfiguration, BucketName.DEFAULT)));
diff --git a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/cache/CachedBlobStoreTest.java b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/cache/CachedBlobStoreTest.java
index c96175c..34ed1be 100644
--- a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/cache/CachedBlobStoreTest.java
+++ b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/cache/CachedBlobStoreTest.java
@@ -45,7 +45,7 @@ import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.api.ObjectNotFoundException;
 import org.apache.james.blob.api.TestBlobId;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
-import org.apache.james.blob.cassandra.CassandraBlobStore;
+import org.apache.james.blob.cassandra.CassandraBlobStoreFactory;
 import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.assertj.core.api.SoftAssertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -74,7 +74,7 @@ public class CachedBlobStoreTest implements BlobStoreContract {
 
     @BeforeEach
     void setUp(CassandraCluster cassandra) {
-        backend = CassandraBlobStore.forTesting(cassandra.getConf());
+        backend = CassandraBlobStoreFactory.forTesting(cassandra.getConf());
         CassandraCacheConfiguration cacheConfig = new CassandraCacheConfiguration.Builder()
             .sizeThresholdInBytes(EIGHT_KILOBYTES.length + 1)
             .timeOut(Duration.ofSeconds(60))
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreDependenciesModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreDependenciesModule.java
index ea5b1a7..22dfc63 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreDependenciesModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreDependenciesModule.java
@@ -22,9 +22,10 @@ package org.apache.james.modules.mailbox;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.blob.api.BucketName;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
-import org.apache.james.blob.cassandra.CassandraBlobStore;
+import org.apache.james.blob.cassandra.CassandraBlobStoreFactory;
 import org.apache.james.blob.cassandra.CassandraDefaultBucketDAO;
 import org.apache.james.blob.cassandra.CassandraDumbBlobStore;
+import org.apache.james.server.blob.deduplication.DeDuplicationBlobStore;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Scopes;
@@ -35,11 +36,11 @@ public class CassandraBlobStoreDependenciesModule extends AbstractModule {
     @Override
     protected void configure() {
         bind(CassandraDefaultBucketDAO.class).in(Scopes.SINGLETON);
-        bind(CassandraBlobStore.class).in(Scopes.SINGLETON);
+        bind(CassandraBlobStoreFactory.class).in(Scopes.SINGLETON);
         bind(CassandraDumbBlobStore.class).in(Scopes.SINGLETON);
 
         bind(BucketName.class)
-            .annotatedWith(Names.named(CassandraDumbBlobStore.DEFAULT_BUCKET))
+            .annotatedWith(Names.named(DeDuplicationBlobStore.DEFAULT_BUCKET()))
             .toInstance(BucketName.DEFAULT);
 
         Multibinder<CassandraModule> cassandraDataDefinitions = Multibinder.newSetBinder(binder(), CassandraModule.class);
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreModule.java
index b4b3dca..23f4981 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraBlobStoreModule.java
@@ -20,17 +20,24 @@
 package org.apache.james.modules.mailbox;
 
 import org.apache.james.blob.api.BlobStore;
+import org.apache.james.blob.api.DumbBlobStore;
 import org.apache.james.blob.api.MetricableBlobStore;
-import org.apache.james.blob.cassandra.CassandraBlobStore;
+import org.apache.james.blob.cassandra.CassandraDumbBlobStore;
+import org.apache.james.server.blob.deduplication.DeDuplicationBlobStore;
 
 import com.google.inject.AbstractModule;
+import com.google.inject.Scopes;
 import com.google.inject.name.Names;
 
 public class CassandraBlobStoreModule extends AbstractModule {
     @Override
     protected void configure() {
+        bind(CassandraDumbBlobStore.class).in(Scopes.SINGLETON);
+        bind(DeDuplicationBlobStore.class).in(Scopes.SINGLETON);
+
+        bind(DumbBlobStore.class).to(CassandraDumbBlobStore.class);
         bind(BlobStore.class)
             .annotatedWith(Names.named(MetricableBlobStore.BLOB_STORE_IMPLEMENTATION))
-            .to(CassandraBlobStore.class);
+            .to(DeDuplicationBlobStore.class);
     }
 }
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/blobstore/BlobStoreModulesChooser.java b/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/blobstore/BlobStoreModulesChooser.java
index 763e66d..b38ea7a 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/blobstore/BlobStoreModulesChooser.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/main/java/org/apache/james/modules/blobstore/BlobStoreModulesChooser.java
@@ -49,9 +49,12 @@ public class BlobStoreModulesChooser {
         @Override
         protected void configure() {
             install(new CassandraBlobStoreDependenciesModule());
+
+            bind(DumbBlobStore.class).to(CassandraDumbBlobStore.class);
+
             bind(BlobStore.class)
                 .annotatedWith(Names.named(CachedBlobStore.BACKEND))
-                .to(CassandraBlobStore.class);
+                .to(DeDuplicationBlobStore.class);
         }
     }
 
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 f329125..0a3be14 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
@@ -24,9 +24,10 @@ import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
+import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
-import org.apache.james.blob.cassandra.CassandraBlobStore;
+import org.apache.james.blob.cassandra.CassandraBlobStoreFactory;
 import org.apache.james.blob.mail.MimeMessageStore;
 import org.apache.james.mailrepository.MailRepositoryContract;
 import org.apache.james.mailrepository.api.MailRepository;
@@ -57,7 +58,7 @@ class CassandraMailRepositoryTest implements MailRepositoryContract {
         CassandraMailRepositoryMailDaoAPI mailDAO = new MergingCassandraMailRepositoryMailDao(v1, v2);
         CassandraMailRepositoryKeysDAO keysDAO = new CassandraMailRepositoryKeysDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
         CassandraMailRepositoryCountDAO countDAO = new CassandraMailRepositoryCountDAO(cassandra.getConf());
-        CassandraBlobStore blobStore = CassandraBlobStore.forTesting(cassandra.getConf());
+        BlobStore blobStore = CassandraBlobStoreFactory.forTesting(cassandra.getConf());
 
         cassandraMailRepository = new CassandraMailRepository(URL,
             keysDAO, countDAO, mailDAO, MimeMessageStore.factory(blobStore).mimeMessageStore());
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 203b594..648a6e9 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
@@ -33,11 +33,12 @@ import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.blob.api.BlobId;
+import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.api.Store;
 import org.apache.james.blob.cassandra.BlobTables;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
-import org.apache.james.blob.cassandra.CassandraBlobStore;
+import org.apache.james.blob.cassandra.CassandraBlobStoreFactory;
 import org.apache.james.blob.mail.MimeMessagePartsId;
 import org.apache.james.blob.mail.MimeMessageStore;
 import org.apache.james.core.builder.MimeMessageBuilder;
@@ -127,7 +128,7 @@ class CassandraMailRepositoryWithFakeImplementationsTest {
             FailingMailDAO mailDAO = new FailingMailDAO();
             keysDAO = new CassandraMailRepositoryKeysDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
             CassandraMailRepositoryCountDAO countDAO = new CassandraMailRepositoryCountDAO(cassandra.getConf());
-            CassandraBlobStore blobStore = CassandraBlobStore.forTesting(cassandra.getConf());
+            BlobStore blobStore = CassandraBlobStoreFactory.forTesting(cassandra.getConf());
 
             cassandraMailRepository = new CassandraMailRepository(URL,
                     keysDAO, countDAO, mailDAO, MimeMessageStore.factory(blobStore).mimeMessageStore());
@@ -212,7 +213,7 @@ class CassandraMailRepositoryWithFakeImplementationsTest {
             CassandraMailRepositoryMailDaoAPI mailDAO = new CassandraMailRepositoryMailDAO(cassandra.getConf(), BLOB_ID_FACTORY, cassandra.getTypesProvider());
             FailingKeysDAO keysDAO = new FailingKeysDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
             countDAO = new CassandraMailRepositoryCountDAO(cassandra.getConf());
-            CassandraBlobStore blobStore = CassandraBlobStore.forTesting(cassandra.getConf());
+            BlobStore blobStore = CassandraBlobStoreFactory.forTesting(cassandra.getConf());
 
             cassandraMailRepository = new CassandraMailRepository(URL,
                     keysDAO, countDAO, mailDAO, MimeMessageStore.factory(blobStore).mimeMessageStore());
diff --git a/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueConfigurationChangeTest.java b/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueConfigurationChangeTest.java
index 74bc055..a863ef8 100644
--- a/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueConfigurationChangeTest.java
+++ b/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueConfigurationChangeTest.java
@@ -36,9 +36,10 @@ import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.backends.rabbitmq.RabbitMQExtension;
+import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
-import org.apache.james.blob.cassandra.CassandraBlobStore;
+import org.apache.james.blob.cassandra.CassandraBlobStoreFactory;
 import org.apache.james.blob.mail.MimeMessageStore;
 import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
 import org.apache.james.metrics.api.NoopGaugeRegistry;
@@ -93,8 +94,8 @@ class RabbitMQMailQueueConfigurationChangeTest {
 
     @BeforeEach
     void setup(CassandraCluster cassandra) throws Exception {
-        CassandraBlobStore blobsDAO = CassandraBlobStore.forTesting(cassandra.getConf());
-        mimeMessageStoreFactory = MimeMessageStore.factory(blobsDAO);
+        BlobStore blobStore = CassandraBlobStoreFactory.forTesting(cassandra.getConf());
+        mimeMessageStoreFactory = MimeMessageStore.factory(blobStore);
         clock = new UpdatableTickingClock(IN_SLICE_1);
         mqManagementApi = new RabbitMQMailQueueManagement(rabbitMQExtension.managementAPI());
     }
diff --git a/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueTest.java b/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueTest.java
index 8808bfc..c6d0691 100644
--- a/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueTest.java
+++ b/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueTest.java
@@ -46,9 +46,10 @@ import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.backends.rabbitmq.RabbitMQExtension;
+import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
-import org.apache.james.blob.cassandra.CassandraBlobStore;
+import org.apache.james.blob.cassandra.CassandraBlobStoreFactory;
 import org.apache.james.blob.mail.MimeMessageStore;
 import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
 import org.apache.james.metrics.api.Gauge;
@@ -76,6 +77,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 import org.mockito.ArgumentCaptor;
 
 import com.github.fge.lambdas.Throwing;
+
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 import reactor.core.scheduler.Schedulers;
@@ -700,7 +702,7 @@ class RabbitMQMailQueueTest {
     private void setUp(CassandraCluster cassandra,
                        MailQueueMetricExtension.MailQueueMetricTestSystem metricTestSystem,
                        RabbitMQMailQueueConfiguration configuration) throws Exception {
-        CassandraBlobStore blobStore = CassandraBlobStore.forTesting(cassandra.getConf());
+        BlobStore blobStore = CassandraBlobStoreFactory.forTesting(cassandra.getConf());
         MimeMessageStore.Factory mimeMessageStoreFactory = MimeMessageStore.factory(blobStore);
         clock = new UpdatableTickingClock(IN_SLICE_1);
 


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