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/24 10:34:33 UTC

[james-project] 02/07: JAMES-3314 implement Passtrough blobstore

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 5e2756371c91e93bced13b795af4cb9a1403681a
Author: RĂ©mi Kowalski <rk...@linagora.com>
AuthorDate: Tue Jul 21 13:48:03 2020 +0200

    JAMES-3314 implement Passtrough blobstore
---
 .../james/vault/DeletedMessageVaultHookTest.java   |  5 +-
 .../blob/BlobStoreDeletedMessageVaultTest.java     |  5 +-
 .../blob/cassandra/CassandraBlobStoreFactory.java  | 17 ++---
 .../blob/cassandra/CassandraBlobStoreTest.java     | 10 +--
 ....java => CassandraPassTroughBlobStoreTest.java} | 13 ++--
 .../file/LocalFileBlobExportMechanismTest.java     |  5 +-
 .../james/blob/memory/MemoryBlobStoreFactory.java  | 15 +----
 .../memory/MemoryBlobStorePassThroughTest.java     |  7 ++-
 .../james/blob/memory/MemoryBlobStoreTest.java     |  5 +-
 .../blob/deduplication/BlobStoreFactory.java       | 72 ++++++++++++++++++++++
 .../blob/deduplication/StorageStrategy.java}       | 21 ++-----
 .../blob/deduplication/PassThroughBlobStore.scala  | 38 +++---------
 .../james/blob/mail/MimeMessageStoreTest.java      |  5 +-
 .../routes/DeletedMessagesVaultRoutesTest.java     |  5 +-
 .../james/webadmin/service/ExportServiceTest.java  |  5 --
 .../webadmin/service/ExportServiceTestSystem.java  |  5 +-
 .../linshare/LinshareBlobExportMechanismTest.java  |  5 +-
 17 files changed, 143 insertions(+), 95 deletions(-)

diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java
index 766fdd9..0fa94af 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java
@@ -109,7 +109,10 @@ class DeletedMessageVaultHookTest {
     void setUp() throws Exception {
         clock = Clock.fixed(DELETION_DATE.toInstant(), ZoneOffset.UTC);
         messageVault = new BlobStoreDeletedMessageVault(new RecordingMetricFactory(), new MemoryDeletedMessageMetadataVault(),
-            MemoryBlobStoreFactory.create(new HashBlobId.Factory()), new BucketNameGenerator(clock), clock,
+            MemoryBlobStoreFactory.builder()
+                .blobIdFactory(new HashBlobId.Factory())
+                .defaultBucketName()
+                .passthrough(), new BucketNameGenerator(clock), clock,
             RetentionConfiguration.DEFAULT);
 
         DeletedMessageConverter deletedMessageConverter = new DeletedMessageConverter();
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/blob/BlobStoreDeletedMessageVaultTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/blob/BlobStoreDeletedMessageVaultTest.java
index a965a89..28b6506 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/blob/BlobStoreDeletedMessageVaultTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/blob/BlobStoreDeletedMessageVaultTest.java
@@ -64,7 +64,10 @@ class BlobStoreDeletedMessageVaultTest implements DeletedMessageVaultContract, D
         clock = new UpdatableTickingClock(NOW.toInstant());
         metricFactory = new RecordingMetricFactory();
         messageVault = new BlobStoreDeletedMessageVault(metricFactory, new MemoryDeletedMessageMetadataVault(),
-            MemoryBlobStoreFactory.create(new HashBlobId.Factory()),
+            MemoryBlobStoreFactory.builder()
+                .blobIdFactory(new HashBlobId.Factory())
+                .defaultBucketName()
+                .passthrough(),
             new BucketNameGenerator(clock), clock, RetentionConfiguration.DEFAULT);
     }
 
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobStoreFactory.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobStoreFactory.java
index cc51047..f1d0576 100644
--- a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobStoreFactory.java
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBlobStoreFactory.java
@@ -23,24 +23,19 @@ import org.apache.james.backends.cassandra.init.configuration.CassandraConfigura
 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.server.blob.deduplication.DeDuplicationBlobStore;
+import org.apache.james.server.blob.deduplication.BlobStoreFactory;
 
 import com.datastax.driver.core.Session;
 
 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));
+        CassandraDumbBlobStore dumbBlobStore = new CassandraDumbBlobStore(defaultBucketDAO, bucketDAO, CassandraConfiguration.DEFAULT_CONFIGURATION, BucketName.DEFAULT);
+        return BlobStoreFactory.builder().dumbBlobStore(dumbBlobStore)
+            .blobIdFactory(blobIdFactory)
+            .defaultBucketName()
+            .passthrough();
     }
 }
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 cf43ad5..ae9136b 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
@@ -40,6 +40,7 @@ import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.api.MetricableBlobStore;
 import org.apache.james.blob.api.MetricableBlobStoreContract;
 import org.apache.james.blob.api.ObjectStoreException;
+import org.apache.james.server.blob.deduplication.BlobStoreFactory;
 import org.apache.james.util.io.ZeroedInputStream;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -71,10 +72,11 @@ public class CassandraBlobStoreTest implements MetricableBlobStoreContract {
             .build();
         testee = new MetricableBlobStore(
             metricsTestExtension.getMetricFactory(),
-            CassandraBlobStoreFactory.forTesting(
-                blobIdFactory,
-                BucketName.DEFAULT,
-                new CassandraDumbBlobStore(defaultBucketDAO, bucketDAO, cassandraConfiguration, BucketName.DEFAULT)));
+            BlobStoreFactory.builder()
+                .dumbBlobStore(new CassandraDumbBlobStore(defaultBucketDAO, bucketDAO, cassandraConfiguration, BucketName.DEFAULT))
+                .blobIdFactory(blobIdFactory)
+                .defaultBucketName()
+                .deduplication());
     }
 
     @Override
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/CassandraPassTroughBlobStoreTest.java
similarity index 93%
copy from server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobStoreTest.java
copy to server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraPassTroughBlobStoreTest.java
index cf43ad5..9ea1731 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/CassandraPassTroughBlobStoreTest.java
@@ -40,6 +40,7 @@ import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.api.MetricableBlobStore;
 import org.apache.james.blob.api.MetricableBlobStoreContract;
 import org.apache.james.blob.api.ObjectStoreException;
+import org.apache.james.server.blob.deduplication.BlobStoreFactory;
 import org.apache.james.util.io.ZeroedInputStream;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -48,10 +49,9 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 import com.google.common.base.Strings;
 import com.google.common.hash.Hashing;
 import com.google.common.hash.HashingInputStream;
-
 import reactor.core.publisher.Mono;
 
-public class CassandraBlobStoreTest implements MetricableBlobStoreContract {
+public class CassandraPassTroughBlobStoreTest implements MetricableBlobStoreContract {
     private static final int CHUNK_SIZE = 10240;
     private static final int MULTIPLE_CHUNK_SIZE = 3;
 
@@ -71,10 +71,11 @@ public class CassandraBlobStoreTest implements MetricableBlobStoreContract {
             .build();
         testee = new MetricableBlobStore(
             metricsTestExtension.getMetricFactory(),
-            CassandraBlobStoreFactory.forTesting(
-                blobIdFactory,
-                BucketName.DEFAULT,
-                new CassandraDumbBlobStore(defaultBucketDAO, bucketDAO, cassandraConfiguration, BucketName.DEFAULT)));
+                BlobStoreFactory.builder()
+                    .dumbBlobStore(new CassandraDumbBlobStore(defaultBucketDAO, bucketDAO, cassandraConfiguration, BucketName.DEFAULT))
+                    .blobIdFactory(blobIdFactory)
+                    .defaultBucketName()
+                    .passthrough());
     }
 
     @Override
diff --git a/server/blob/blob-export-file/src/test/java/org/apache/james/blob/export/file/LocalFileBlobExportMechanismTest.java b/server/blob/blob-export-file/src/test/java/org/apache/james/blob/export/file/LocalFileBlobExportMechanismTest.java
index 4eff0c4..5655d0e 100644
--- a/server/blob/blob-export-file/src/test/java/org/apache/james/blob/export/file/LocalFileBlobExportMechanismTest.java
+++ b/server/blob/blob-export-file/src/test/java/org/apache/james/blob/export/file/LocalFileBlobExportMechanismTest.java
@@ -67,7 +67,10 @@ class LocalFileBlobExportMechanismTest {
     @BeforeEach
     void setUp(FileSystem fileSystem) throws Exception {
         mailetContext = FakeMailContext.builder().postmaster(MailAddressFixture.POSTMASTER_AT_JAMES).build();
-        blobStore = MemoryBlobStoreFactory.create(new HashBlobId.Factory());
+        blobStore = MemoryBlobStoreFactory.builder()
+            .blobIdFactory(new HashBlobId.Factory())
+            .defaultBucketName()
+            .passthrough();
 
         InetAddress localHost = mock(InetAddress.class);
         when(localHost.getHostName()).thenReturn(JAMES_HOST);
diff --git a/server/blob/blob-memory/src/main/java/org/apache/james/blob/memory/MemoryBlobStoreFactory.java b/server/blob/blob-memory/src/main/java/org/apache/james/blob/memory/MemoryBlobStoreFactory.java
index 5e7c7e2..bc59922 100644
--- a/server/blob/blob-memory/src/main/java/org/apache/james/blob/memory/MemoryBlobStoreFactory.java
+++ b/server/blob/blob-memory/src/main/java/org/apache/james/blob/memory/MemoryBlobStoreFactory.java
@@ -19,19 +19,10 @@
 
 package org.apache.james.blob.memory;
 
-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.server.blob.deduplication.DeDuplicationBlobStore;
+import org.apache.james.server.blob.deduplication.BlobStoreFactory;
 
 public class MemoryBlobStoreFactory {
-    public static BlobStore create(BlobId.Factory factory) {
-        return create(factory, BucketName.DEFAULT);
-    }
-
-    public static BlobStore create(BlobId.Factory factory, BucketName defaultBucketName) {
-        return new DeDuplicationBlobStore(
-            new MemoryDumbBlobStore(),
-            defaultBucketName, factory);
+    public static BlobStoreFactory.RequireBlobIdFactory builder() {
+        return BlobStoreFactory.builder().dumbBlobStore(new MemoryDumbBlobStore());
     }
 }
diff --git a/server/blob/blob-memory/src/test/java/org/apache/james/blob/memory/MemoryBlobStorePassThroughTest.java b/server/blob/blob-memory/src/test/java/org/apache/james/blob/memory/MemoryBlobStorePassThroughTest.java
index 80dba7e..aa72550 100644
--- a/server/blob/blob-memory/src/test/java/org/apache/james/blob/memory/MemoryBlobStorePassThroughTest.java
+++ b/server/blob/blob-memory/src/test/java/org/apache/james/blob/memory/MemoryBlobStorePassThroughTest.java
@@ -26,14 +26,17 @@ import org.apache.james.blob.api.MetricableBlobStore;
 import org.apache.james.blob.api.MetricableBlobStoreContract;
 import org.junit.jupiter.api.BeforeEach;
 
-public class MemoryBlobStoreTest implements MetricableBlobStoreContract {
+public class MemoryBlobStorePassThroughTest implements MetricableBlobStoreContract {
 
     private static final HashBlobId.Factory BLOB_ID_FACTORY = new HashBlobId.Factory();
     private BlobStore blobStore;
 
     @BeforeEach
     void setUp() {
-        blobStore = new MetricableBlobStore(metricsTestExtension.getMetricFactory(), MemoryBlobStoreFactory.create(BLOB_ID_FACTORY));
+        blobStore = new MetricableBlobStore(metricsTestExtension.getMetricFactory(), MemoryBlobStoreFactory.builder()
+                .blobIdFactory(BLOB_ID_FACTORY)
+                .defaultBucketName()
+                .passthrough());
     }
 
     @Override
diff --git a/server/blob/blob-memory/src/test/java/org/apache/james/blob/memory/MemoryBlobStoreTest.java b/server/blob/blob-memory/src/test/java/org/apache/james/blob/memory/MemoryBlobStoreTest.java
index 80dba7e..147133c 100644
--- a/server/blob/blob-memory/src/test/java/org/apache/james/blob/memory/MemoryBlobStoreTest.java
+++ b/server/blob/blob-memory/src/test/java/org/apache/james/blob/memory/MemoryBlobStoreTest.java
@@ -33,7 +33,10 @@ public class MemoryBlobStoreTest implements MetricableBlobStoreContract {
 
     @BeforeEach
     void setUp() {
-        blobStore = new MetricableBlobStore(metricsTestExtension.getMetricFactory(), MemoryBlobStoreFactory.create(BLOB_ID_FACTORY));
+        blobStore = new MetricableBlobStore(metricsTestExtension.getMetricFactory(), new MetricableBlobStore(metricsTestExtension.getMetricFactory(), MemoryBlobStoreFactory.builder()
+                .blobIdFactory(BLOB_ID_FACTORY)
+                .defaultBucketName()
+                .deduplication()));
     }
 
     @Override
diff --git a/server/blob/blob-storage-strategy/src/main/java/org/apache/james/server/blob/deduplication/BlobStoreFactory.java b/server/blob/blob-storage-strategy/src/main/java/org/apache/james/server/blob/deduplication/BlobStoreFactory.java
new file mode 100644
index 0000000..4a3fdc3
--- /dev/null
+++ b/server/blob/blob-storage-strategy/src/main/java/org/apache/james/server/blob/deduplication/BlobStoreFactory.java
@@ -0,0 +1,72 @@
+/****************************************************************
+ * 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.server.blob.deduplication;
+
+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.DumbBlobStore;
+
+public abstract class BlobStoreFactory {
+    @FunctionalInterface
+    public interface RequireDumbBlobStore {
+        RequireBlobIdFactory dumbBlobStore(DumbBlobStore dumbBlobStore);
+    }
+
+    @FunctionalInterface
+    public interface RequireBlobIdFactory {
+        RequireBucketName blobIdFactory(BlobId.Factory blobIdFactory);
+    }
+
+    @FunctionalInterface
+    public interface RequireBucketName {
+        RequireStoringStrategy bucket(BucketName defaultBucketName);
+
+        default RequireStoringStrategy defaultBucketName() {
+            return bucket(BucketName.DEFAULT);
+        }
+    }
+
+    @FunctionalInterface
+    public interface RequireStoringStrategy {
+        BlobStore strategy(StorageStrategy storageStrategy);
+
+        default BlobStore passthrough() {
+            return strategy(StorageStrategy.PASSTHROUGH);
+        }
+
+        default BlobStore deduplication() {
+            return strategy(StorageStrategy.DEDUPLICATION);
+        }
+    }
+
+    public static RequireDumbBlobStore builder() {
+        return dumbBlobStore -> blobIdFactory -> defaultBucketName -> storageStrategy -> {
+            switch (storageStrategy) {
+                case PASSTHROUGH:
+                    return new PassThroughBlobStore(dumbBlobStore, defaultBucketName, blobIdFactory);
+                case DEDUPLICATION:
+                    return new DeDuplicationBlobStore(dumbBlobStore, defaultBucketName, blobIdFactory);
+                default:
+                    throw new IllegalArgumentException("Unknown storage strategy");
+            }
+        };
+    }
+}
diff --git a/server/blob/blob-memory/src/main/java/org/apache/james/blob/memory/MemoryBlobStoreFactory.java b/server/blob/blob-storage-strategy/src/main/java/org/apache/james/server/blob/deduplication/StorageStrategy.java
similarity index 65%
copy from server/blob/blob-memory/src/main/java/org/apache/james/blob/memory/MemoryBlobStoreFactory.java
copy to server/blob/blob-storage-strategy/src/main/java/org/apache/james/server/blob/deduplication/StorageStrategy.java
index 5e7c7e2..91d2df1 100644
--- a/server/blob/blob-memory/src/main/java/org/apache/james/blob/memory/MemoryBlobStoreFactory.java
+++ b/server/blob/blob-storage-strategy/src/main/java/org/apache/james/server/blob/deduplication/StorageStrategy.java
@@ -16,22 +16,9 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
+package org.apache.james.server.blob.deduplication;
 
-package org.apache.james.blob.memory;
-
-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.server.blob.deduplication.DeDuplicationBlobStore;
-
-public class MemoryBlobStoreFactory {
-    public static BlobStore create(BlobId.Factory factory) {
-        return create(factory, BucketName.DEFAULT);
-    }
-
-    public static BlobStore create(BlobId.Factory factory, BucketName defaultBucketName) {
-        return new DeDuplicationBlobStore(
-            new MemoryDumbBlobStore(),
-            defaultBucketName, factory);
-    }
+public enum StorageStrategy {
+    PASSTHROUGH,
+    DEDUPLICATION
 }
diff --git a/server/blob/blob-storage-strategy/src/main/scala/org/apache/james/server/blob/deduplication/PassThroughBlobStore.scala b/server/blob/blob-storage-strategy/src/main/scala/org/apache/james/server/blob/deduplication/PassThroughBlobStore.scala
index 5bd663f..5f29ffd 100644
--- a/server/blob/blob-storage-strategy/src/main/scala/org/apache/james/server/blob/deduplication/PassThroughBlobStore.scala
+++ b/server/blob/blob-storage-strategy/src/main/scala/org/apache/james/server/blob/deduplication/PassThroughBlobStore.scala
@@ -22,31 +22,21 @@ package org.apache.james.server.blob.deduplication
 import java.io.InputStream
 
 import com.google.common.base.Preconditions
-import com.google.common.hash.{Hashing, HashingInputStream}
-import com.google.common.io.{ByteSource, FileBackedOutputStream}
 import javax.inject.{Inject, Named}
-import org.apache.commons.io.IOUtils
 import org.apache.james.blob.api.{BlobId, BlobStore, BucketName, DumbBlobStore}
 import org.reactivestreams.Publisher
-import reactor.core.publisher.Mono
 import reactor.core.scala.publisher.SMono
-import reactor.util.function.{Tuple2, Tuples}
 
-object DeDuplicationBlobStore {
-  val DEFAULT_BUCKET = "defaultBucket"
-  val LAZY_RESOURCE_CLEANUP = false
-  val FILE_THRESHOLD = 10000
-}
 
-class DeDuplicationBlobStore @Inject()(dumbBlobStore: DumbBlobStore,
-                                       @Named("defaultBucket") defaultBucketName: BucketName,
-                                       blobIdFactory: BlobId.Factory) extends BlobStore {
+class PassThroughBlobStore @Inject()(dumbBlobStore: DumbBlobStore,
+                                     @Named("defaultBucket") defaultBucketName: BucketName,
+                                     blobIdFactory: BlobId.Factory) extends BlobStore {
 
   override def save(bucketName: BucketName, data: Array[Byte], storagePolicy: BlobStore.StoragePolicy): Publisher[BlobId] = {
     Preconditions.checkNotNull(bucketName)
     Preconditions.checkNotNull(data)
 
-    val blobId = blobIdFactory.forPayload(data)
+    val blobId = blobIdFactory.randomId()
 
     SMono(dumbBlobStore.save(bucketName, blobId, data))
       .`then`(SMono.just(blobId))
@@ -55,23 +45,11 @@ class DeDuplicationBlobStore @Inject()(dumbBlobStore: DumbBlobStore,
   override def save(bucketName: BucketName, data: InputStream, storagePolicy: BlobStore.StoragePolicy): Publisher[BlobId] = {
     Preconditions.checkNotNull(bucketName)
     Preconditions.checkNotNull(data)
-    val hashingInputStream = new HashingInputStream(Hashing.sha256, data)
-    val sourceSupplier: FileBackedOutputStream => SMono[BlobId] = (fileBackedOutputStream: FileBackedOutputStream) => saveAndGenerateBlobId(bucketName, hashingInputStream, fileBackedOutputStream)
-    Mono.using(() => new FileBackedOutputStream(DeDuplicationBlobStore.FILE_THRESHOLD),
-      sourceSupplier,
-      (fileBackedOutputStream: FileBackedOutputStream) => fileBackedOutputStream.reset(),
-      DeDuplicationBlobStore.LAZY_RESOURCE_CLEANUP)
-  }
-
-  private def saveAndGenerateBlobId(bucketName: BucketName, hashingInputStream: HashingInputStream, fileBackedOutputStream: FileBackedOutputStream): SMono[BlobId] =
-    SMono.fromCallable(() => {
-      IOUtils.copy(hashingInputStream, fileBackedOutputStream)
-      Tuples.of(blobIdFactory.from(hashingInputStream.hash.toString), fileBackedOutputStream.asByteSource)
-    })
-      .flatMap((tuple: Tuple2[BlobId, ByteSource]) =>
-        SMono(dumbBlobStore.save(bucketName, tuple.getT1, tuple.getT2))
-          .`then`(SMono.just(tuple.getT1)))
+    val blobId = blobIdFactory.randomId()
 
+    SMono(dumbBlobStore.save(bucketName, blobId, data))
+      .`then`(SMono.just(blobId))
+  }
 
   override def readBytes(bucketName: BucketName, blobId: BlobId): Publisher[Array[Byte]] = {
     Preconditions.checkNotNull(bucketName)
diff --git a/server/blob/mail-store/src/test/java/org/apache/james/blob/mail/MimeMessageStoreTest.java b/server/blob/mail-store/src/test/java/org/apache/james/blob/mail/MimeMessageStoreTest.java
index e1dda9a..bb24ab5 100644
--- a/server/blob/mail-store/src/test/java/org/apache/james/blob/mail/MimeMessageStoreTest.java
+++ b/server/blob/mail-store/src/test/java/org/apache/james/blob/mail/MimeMessageStoreTest.java
@@ -47,7 +47,10 @@ class MimeMessageStoreTest {
 
     @BeforeEach
     void setUp() {
-        blobStore = MemoryBlobStoreFactory.create(BLOB_ID_FACTORY);
+        blobStore = MemoryBlobStoreFactory.builder()
+            .blobIdFactory(BLOB_ID_FACTORY)
+            .defaultBucketName()
+            .passthrough();
         testee = MimeMessageStore.factory(blobStore).mimeMessageStore();
     }
 
diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
index 43004e0..3cf3d00 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
@@ -176,7 +176,10 @@ class DeletedMessagesVaultRoutesTest {
     @BeforeEach
     void beforeEach() throws Exception {
         blobIdFactory = new HashBlobId.Factory();
-        blobStore = spy(MemoryBlobStoreFactory.create(blobIdFactory));
+        blobStore = spy(MemoryBlobStoreFactory.builder()
+            .blobIdFactory(blobIdFactory)
+            .defaultBucketName()
+            .passthrough());
         clock = new UpdatableTickingClock(OLD_DELETION_DATE.toInstant());
         vault = spy(new BlobStoreDeletedMessageVault(new RecordingMetricFactory(), new MemoryDeletedMessageMetadataVault(),
             blobStore, new BucketNameGenerator(clock), clock,
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExportServiceTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExportServiceTest.java
index fa0c391..c016b59 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExportServiceTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExportServiceTest.java
@@ -206,11 +206,6 @@ class ExportServiceTest {
 
         Task.Result result = testee.export(progress, BOB).block();
 
-        String fileName = Files.getNameWithoutExtension(getFileUrl());
-        String blobId = fileName.substring(fileName.lastIndexOf("-") + 1);
-
-        testSystem.blobStore.read(testSystem.blobStore.getDefaultBucketName(), FACTORY.from(blobId));
-
         assertThat(result).isEqualTo(Task.Result.COMPLETED);
     }
 
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExportServiceTestSystem.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExportServiceTestSystem.java
index 389ffad..c7b0b94 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExportServiceTestSystem.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/ExportServiceTestSystem.java
@@ -76,7 +76,10 @@ public class ExportServiceTestSystem {
 
         bobSession = mailboxManager.createSystemSession(BOB);
 
-        blobStore = Mockito.spy(MemoryBlobStoreFactory.create(FACTORY));
+        blobStore = Mockito.spy(MemoryBlobStoreFactory.builder()
+            .blobIdFactory(FACTORY)
+            .defaultBucketName()
+            .passthrough());
         mailetContext = FakeMailContext.builder().postmaster(MailAddressFixture.POSTMASTER_AT_JAMES).build();
         blobExport = new LocalFileBlobExportMechanism(mailetContext, blobStore, fileSystem, dnsService,
             LocalFileBlobExportMechanism.Configuration.DEFAULT_CONFIGURATION);
diff --git a/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareBlobExportMechanismTest.java b/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareBlobExportMechanismTest.java
index 738d4b0..4ed698e 100644
--- a/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareBlobExportMechanismTest.java
+++ b/third-party/linshare/src/test/java/org/apache/james/linshare/LinshareBlobExportMechanismTest.java
@@ -58,7 +58,10 @@ class LinshareBlobExportMechanismTest {
     @BeforeEach
     void setUp() throws Exception {
         blobIdFactory = new HashBlobId.Factory();
-        blobStore = MemoryBlobStoreFactory.create(blobIdFactory);
+        blobStore = MemoryBlobStoreFactory.builder()
+            .blobIdFactory(blobIdFactory)
+            .defaultBucketName()
+            .passthrough();
 
         testee = new LinshareBlobExportMechanism(
             linshareExtension.getDelegationAccountAPI(),


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