JAMES-2599 Implement MetricableBlobStore and test it
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/a39ed230 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/a39ed230 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/a39ed230 Branch: refs/heads/master Commit: a39ed230ddb4cd907860dc540897605a9410c3ec Parents: d81ab10 Author: tran tien duc <[email protected]> Authored: Thu Nov 22 10:10:58 2018 +0700 Committer: Benoit Tellier <[email protected]> Committed: Thu Nov 22 17:50:42 2018 +0700 ---------------------------------------------------------------------- .../james/blob/api/MetricableBlobStore.java | 65 ++++++++++++++++++++ server/blob/blob-cassandra/pom.xml | 5 ++ .../blob/cassandra/CassandraBlobsDAOTest.java | 19 +++--- server/blob/blob-memory/pom.xml | 5 ++ .../james/blob/memory/MemoryBlobStoreTest.java | 11 ++-- server/blob/blob-objectstorage/pom.xml | 6 +- .../ObjectStorageBlobsDAOTest.java | 39 ++++++------ 7 files changed, 117 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/a39ed230/server/blob/blob-api/src/main/java/org/apache/james/blob/api/MetricableBlobStore.java ---------------------------------------------------------------------- diff --git a/server/blob/blob-api/src/main/java/org/apache/james/blob/api/MetricableBlobStore.java b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/MetricableBlobStore.java new file mode 100644 index 0000000..d40a1ac --- /dev/null +++ b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/MetricableBlobStore.java @@ -0,0 +1,65 @@ +/**************************************************************** + * 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.api; + +import java.io.InputStream; +import java.util.concurrent.CompletableFuture; + +import org.apache.james.metrics.api.MetricFactory; + +public class MetricableBlobStore implements BlobStore { + + static final String BLOB_STORE_METRIC_PREFIX = "blobStore:"; + static final String SAVE_BYTES_TIMER_NAME = BLOB_STORE_METRIC_PREFIX + "saveBytes"; + static final String SAVE_INPUT_STREAM_TIMER_NAME = BLOB_STORE_METRIC_PREFIX + "saveInputStream"; + static final String READ_BYTES_TIMER_NAME = BLOB_STORE_METRIC_PREFIX + "readBytes"; + static final String READ_TIMER_NAME = BLOB_STORE_METRIC_PREFIX + "read"; + + private final MetricFactory metricFactory; + private final BlobStore blobStoreImpl; + + public MetricableBlobStore(MetricFactory metricFactory, BlobStore blobStoreImpl) { + this.metricFactory = metricFactory; + this.blobStoreImpl = blobStoreImpl; + } + + @Override + public CompletableFuture<BlobId> save(byte[] data) { + return metricFactory + .runPublishingTimerMetric(SAVE_BYTES_TIMER_NAME, blobStoreImpl.save(data)); + } + + @Override + public CompletableFuture<BlobId> save(InputStream data) { + return metricFactory + .runPublishingTimerMetric(SAVE_INPUT_STREAM_TIMER_NAME, blobStoreImpl.save(data)); + } + + @Override + public CompletableFuture<byte[]> readBytes(BlobId blobId) { + return metricFactory + .runPublishingTimerMetric(READ_BYTES_TIMER_NAME, blobStoreImpl.readBytes(blobId)); + } + + @Override + public InputStream read(BlobId blobId) { + return metricFactory + .runPublishingTimerMetric(READ_TIMER_NAME, () -> blobStoreImpl.read(blobId)); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/a39ed230/server/blob/blob-cassandra/pom.xml ---------------------------------------------------------------------- diff --git a/server/blob/blob-cassandra/pom.xml b/server/blob/blob-cassandra/pom.xml index e88e935..42a77ef 100644 --- a/server/blob/blob-cassandra/pom.xml +++ b/server/blob/blob-cassandra/pom.xml @@ -86,6 +86,11 @@ <artifactId>testcontainers</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> http://git-wip-us.apache.org/repos/asf/james-project/blob/a39ed230/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java ---------------------------------------------------------------------- diff --git a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java index a37215e..b7d7980 100644 --- a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java +++ b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBlobsDAOTest.java @@ -28,30 +28,33 @@ import org.apache.james.backends.cassandra.CassandraClusterExtension; 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.BlobStoreContract; import org.apache.james.blob.api.HashBlobId; +import org.apache.james.blob.api.MetricableBlobStore; +import org.apache.james.blob.api.MetricableBlobStoreContract; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import com.google.common.base.Strings; -public class CassandraBlobsDAOTest implements BlobStoreContract { +public class CassandraBlobsDAOTest implements MetricableBlobStoreContract { private static final int CHUNK_SIZE = 10240; private static final int MULTIPLE_CHUNK_SIZE = 3; @RegisterExtension static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(CassandraBlobModule.MODULE); - private CassandraBlobsDAO testee; + private BlobStore testee; @BeforeEach void setUp(CassandraCluster cassandra) { - testee = new CassandraBlobsDAO(cassandra.getConf(), - CassandraConfiguration.builder() - .blobPartSize(CHUNK_SIZE) - .build(), - new HashBlobId.Factory()); + testee = new MetricableBlobStore( + metricsTestExtension.getMetricFactory(), + new CassandraBlobsDAO(cassandra.getConf(), + CassandraConfiguration.builder() + .blobPartSize(CHUNK_SIZE) + .build(), + new HashBlobId.Factory())); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/a39ed230/server/blob/blob-memory/pom.xml ---------------------------------------------------------------------- diff --git a/server/blob/blob-memory/pom.xml b/server/blob/blob-memory/pom.xml index 240f67a..c961d2d 100644 --- a/server/blob/blob-memory/pom.xml +++ b/server/blob/blob-memory/pom.xml @@ -61,6 +61,11 @@ <artifactId>junit-platform-launcher</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/a39ed230/server/blob/blob-memory/src/test/java/org/apache/james/blob/memory/MemoryBlobStoreTest.java ---------------------------------------------------------------------- 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 098506a..6dbac34 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 @@ -21,23 +21,24 @@ 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.BlobStoreContract; import org.apache.james.blob.api.HashBlobId; +import org.apache.james.blob.api.MetricableBlobStore; +import org.apache.james.blob.api.MetricableBlobStoreContract; import org.junit.jupiter.api.BeforeEach; -public class MemoryBlobStoreTest implements BlobStoreContract { +public class MemoryBlobStoreTest implements MetricableBlobStoreContract { private static final HashBlobId.Factory BLOB_ID_FACTORY = new HashBlobId.Factory(); - private MemoryBlobStore memoryBlobStore; + private BlobStore blobStore; @BeforeEach void setUp() { - memoryBlobStore = new MemoryBlobStore(BLOB_ID_FACTORY); + blobStore = new MetricableBlobStore(metricsTestExtension.getMetricFactory(), new MemoryBlobStore(BLOB_ID_FACTORY)); } @Override public BlobStore testee() { - return memoryBlobStore; + return blobStore; } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/a39ed230/server/blob/blob-objectstorage/pom.xml ---------------------------------------------------------------------- diff --git a/server/blob/blob-objectstorage/pom.xml b/server/blob/blob-objectstorage/pom.xml index fa93b96..6a35af0 100644 --- a/server/blob/blob-objectstorage/pom.xml +++ b/server/blob/blob-objectstorage/pom.xml @@ -110,7 +110,11 @@ <artifactId>testcontainers</artifactId> <scope>test</scope> </dependency> - + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> </dependencies> <build> http://git-wip-us.apache.org/repos/asf/james-project/blob/a39ed230/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAOTest.java ---------------------------------------------------------------------- diff --git a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAOTest.java b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAOTest.java index e76477f..c5deef5 100644 --- a/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAOTest.java +++ b/server/blob/blob-objectstorage/src/test/java/org/apache/james/blob/objectstorage/ObjectStorageBlobsDAOTest.java @@ -30,8 +30,9 @@ import java.util.UUID; import org.apache.commons.io.IOUtils; import org.apache.james.blob.api.BlobId; import org.apache.james.blob.api.BlobStore; -import org.apache.james.blob.api.BlobStoreContract; 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.blob.objectstorage.crypto.CryptoConfig; import org.apache.james.blob.objectstorage.swift.Credentials; @@ -47,26 +48,25 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(DockerSwiftExtension.class) -public class ObjectStorageBlobsDAOTest implements BlobStoreContract { +public class ObjectStorageBlobsDAOTest implements MetricableBlobStoreContract { private static final TenantName TENANT_NAME = TenantName.of("test"); private static final UserName USER_NAME = UserName.of("tester"); private static final Credentials PASSWORD = Credentials.of("testing"); private static final Identity SWIFT_IDENTITY = Identity.of(TENANT_NAME, USER_NAME); - private static final InputStream EMPTY_STREAM = new ByteArrayInputStream(new byte[]{}); - - public static final String SAMPLE_SALT = "c603a7327ee3dcbc031d8d34b1096c605feca5e1"; + private static final String SAMPLE_SALT = "c603a7327ee3dcbc031d8d34b1096c605feca5e1"; + private static final CryptoConfig CRYPTO_CONFIG = CryptoConfig.builder() + .salt(SAMPLE_SALT) + .password(PASSWORD.value().toCharArray()) + .build(); private ContainerName containerName; private org.jclouds.blobstore.BlobStore blobStore; private SwiftTempAuthObjectStorage.Configuration testConfig; - private ObjectStorageBlobsDAO testee; - public static final CryptoConfig CRYPTO_CONFIG = CryptoConfig.builder() - .salt(SAMPLE_SALT) - .password(PASSWORD.value().toCharArray()) - .build(); + private ObjectStorageBlobsDAO objectStorageBlobsDAO; + private BlobStore testee; @BeforeEach - void setUp(DockerSwift dockerSwift) throws Exception { + void setUp(DockerSwift dockerSwift) { containerName = ContainerName.of(UUID.randomUUID().toString()); testConfig = SwiftTempAuthObjectStorage.configBuilder() .endpoint(dockerSwift.swiftEndpoint()) @@ -81,12 +81,13 @@ public class ObjectStorageBlobsDAOTest implements BlobStoreContract { .container(containerName) .blobIdFactory(blobIdFactory); blobStore = daoBuilder.getSupplier().get(); - testee = daoBuilder.build(); - testee.createContainer(containerName); + objectStorageBlobsDAO = daoBuilder.build(); + objectStorageBlobsDAO.createContainer(containerName); + testee = new MetricableBlobStore(metricsTestExtension.getMetricFactory(), objectStorageBlobsDAO); } @AfterEach - void tearDown() throws Exception { + void tearDown() { blobStore.deleteContainer(containerName.value()); blobStore.getContext().close(); } @@ -104,21 +105,21 @@ public class ObjectStorageBlobsDAOTest implements BlobStoreContract { @Test void createContainerShouldMakeTheContainerToExist() throws Exception { ContainerName containerName = ContainerName.of(UUID.randomUUID().toString()); - testee.createContainer(containerName).get(); + objectStorageBlobsDAO.createContainer(containerName).get(); assertThat(blobStore.containerExists(containerName.value())).isTrue(); } @Test void createContainerShouldFailWithRuntimeExceptionWhenCreateContainerTwice() throws Exception { ContainerName containerName = ContainerName.of(UUID.randomUUID().toString()); - testee.createContainer(containerName).get(); - assertThatThrownBy(() -> testee.createContainer(containerName).get()) + objectStorageBlobsDAO.createContainer(containerName).get(); + assertThatThrownBy(() -> objectStorageBlobsDAO.createContainer(containerName).get()) .hasCauseInstanceOf(ObjectStoreException.class) .hasMessageContaining("Unable to create container"); } @Test - void supportsEncryptionWithCustomPayloadCodec() throws Exception { + void supportsEncryptionWithCustomPayloadCodec() { ObjectStorageBlobsDAO encryptedDao = ObjectStorageBlobsDAO .builder(testConfig) .container(containerName) @@ -154,7 +155,7 @@ public class ObjectStorageBlobsDAOTest implements BlobStoreContract { @Test void deleteContainerShouldDeleteSwiftContainer() { - testee.deleteContainer(); + objectStorageBlobsDAO.deleteContainer(); assertThat(blobStore.containerExists(containerName.value())) .isFalse(); } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
