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 2019/08/01 07:31:01 UTC

[james-project] 08/20: JAMES-2838 delete support at the DAO layer

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 f3dbce76e2ff1f3a57a86f58274b120650317255
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Jul 25 11:24:09 2019 +0200

    JAMES-2838 delete support at the DAO layer
---
 .../james/blob/cassandra/CassandraBucketDAO.java   | 33 ++++++++++++++++
 .../blob/cassandra/CassandraDefaultBucketDAO.java  | 31 ++++++++++++++-
 .../blob/cassandra/CassandraBucketDAOTest.java     | 46 ++++++++++++++++++++++
 .../cassandra/CassandraDefaultBucketDAOTest.java   | 46 ++++++++++++++++++++++
 4 files changed, 155 insertions(+), 1 deletion(-)

diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBucketDAO.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBucketDAO.java
index 8c3484d..713429f 100644
--- a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBucketDAO.java
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraBucketDAO.java
@@ -20,6 +20,7 @@
 package org.apache.james.blob.cassandra;
 
 import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.delete;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
@@ -49,6 +50,8 @@ public class CassandraBucketDAO {
     private final PreparedStatement insertPart;
     private final PreparedStatement select;
     private final PreparedStatement selectPart;
+    private final PreparedStatement delete;
+    private final PreparedStatement deleteParts;
 
     @Inject
     @VisibleForTesting
@@ -56,8 +59,24 @@ public class CassandraBucketDAO {
         this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session);
         this.insert = prepareInsert(session);
         this.select = prepareSelect(session);
+        this.delete = prepareDelete(session);
         this.insertPart = prepareInsertPart(session);
         this.selectPart = prepareSelectPart(session);
+        this.deleteParts = prepareDeleteParts(session);
+    }
+
+    private PreparedStatement prepareDeleteParts(Session session) {
+        return session.prepare(
+            delete().from(BucketBlobParts.TABLE_NAME)
+                .where(eq(BucketBlobParts.BUCKET, bindMarker(BucketBlobParts.BUCKET)))
+                .and(eq(BucketBlobParts.ID, bindMarker(BucketBlobParts.ID))));
+    }
+
+    private PreparedStatement prepareDelete(Session session) {
+        return session.prepare(
+            delete().from(BlobTables.BucketBlobTable.TABLE_NAME)
+                .where(eq(BUCKET, bindMarker(BUCKET)))
+                .and(eq(ID, bindMarker(ID))));
     }
 
     private PreparedStatement prepareSelect(Session session) {
@@ -124,6 +143,20 @@ public class CassandraBucketDAO {
             .map(this::rowToData);
     }
 
+    Mono<Void> deletePosition(BucketName bucketName, BlobId blobId) {
+        return cassandraAsyncExecutor.executeVoid(
+            delete.bind()
+                .setString(BUCKET, bucketName.asString())
+                .setString(ID, blobId.asString()));
+    }
+
+    Mono<Void> deleteParts(BucketName bucketName, BlobId blobId) {
+        return cassandraAsyncExecutor.executeVoid(
+            deleteParts.bind()
+                .setString(BucketBlobParts.BUCKET, bucketName.asString())
+                .setString(BucketBlobParts.ID, blobId.asString()));
+    }
+
     private byte[] rowToData(Row row) {
         byte[] data = new byte[row.getBytes(BucketBlobParts.DATA).remaining()];
         row.getBytes(BucketBlobParts.DATA).get(data);
diff --git a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraDefaultBucketDAO.java b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraDefaultBucketDAO.java
index fee3108..48c125d 100644
--- a/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraDefaultBucketDAO.java
+++ b/server/blob/blob-cassandra/src/main/java/org/apache/james/blob/cassandra/CassandraDefaultBucketDAO.java
@@ -20,6 +20,7 @@
 package org.apache.james.blob.cassandra;
 
 import static com.datastax.driver.core.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.delete;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.insertInto;
 import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
@@ -47,15 +48,19 @@ public class CassandraDefaultBucketDAO {
     private final PreparedStatement insertPart;
     private final PreparedStatement select;
     private final PreparedStatement selectPart;
+    private final PreparedStatement delete;
+    private final PreparedStatement deleteParts;
 
     @Inject
     @VisibleForTesting
-    public CassandraDefaultBucketDAO(Session session) {
+    CassandraDefaultBucketDAO(Session session) {
         this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session);
         this.insert = prepareInsert(session);
         this.select = prepareSelect(session);
         this.insertPart = prepareInsertPart(session);
         this.selectPart = prepareSelectPart(session);
+        this.delete = prepareDelete(session);
+        this.deleteParts = prepareDeleteParts(session);
     }
 
     private PreparedStatement prepareSelect(Session session) {
@@ -84,6 +89,18 @@ public class CassandraDefaultBucketDAO {
             .value(DefaultBucketBlobParts.DATA, bindMarker(DefaultBucketBlobParts.DATA)));
     }
 
+    private PreparedStatement prepareDeleteParts(Session session) {
+        return session.prepare(
+            delete().from(DefaultBucketBlobParts.TABLE_NAME)
+                .where(eq(DefaultBucketBlobParts.ID, bindMarker(DefaultBucketBlobParts.ID))));
+    }
+
+    private PreparedStatement prepareDelete(Session session) {
+        return session.prepare(
+            delete().from(BlobTables.DefaultBucketBlobTable.TABLE_NAME)
+                .where(eq(BlobTables.DefaultBucketBlobTable.ID, bindMarker(BlobTables.DefaultBucketBlobTable.ID))));
+    }
+
     Mono<Void> writePart(ByteBuffer data, BlobId blobId, int position) {
         return cassandraAsyncExecutor.executeVoid(
             insertPart.bind()
@@ -114,6 +131,18 @@ public class CassandraDefaultBucketDAO {
             .map(this::rowToData);
     }
 
+    Mono<Void> deletePosition(BlobId blobId) {
+        return cassandraAsyncExecutor.executeVoid(
+            delete.bind()
+                .setString(ID, blobId.asString()));
+    }
+
+    Mono<Void> deleteParts(BlobId blobId) {
+        return cassandraAsyncExecutor.executeVoid(
+            deleteParts.bind()
+                .setString(DefaultBucketBlobParts.ID, blobId.asString()));
+    }
+
     private byte[] rowToData(Row row) {
         byte[] data = new byte[row.getBytes(DefaultBucketBlobParts.DATA).remaining()];
         row.getBytes(DefaultBucketBlobParts.DATA).get(data);
diff --git a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBucketDAOTest.java b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBucketDAOTest.java
index 175841a..8994ed4 100644
--- a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBucketDAOTest.java
+++ b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraBucketDAOTest.java
@@ -29,6 +29,7 @@ import static org.apache.james.blob.cassandra.CassandraBlobStoreFixture.NUMBER_O
 import static org.apache.james.blob.cassandra.CassandraBlobStoreFixture.POSITION;
 import static org.apache.james.blob.cassandra.CassandraBlobStoreFixture.POSITION_2;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 
 import java.nio.ByteBuffer;
 import java.util.Optional;
@@ -58,6 +59,51 @@ class CassandraBucketDAOTest {
     }
 
     @Test
+    void deletePositionShouldNotThrowWhenMissing() {
+        assertThatCode(() -> testee.deletePosition(BUCKET_NAME, BLOB_ID).block())
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    void deletePartShouldNotThrowWhenMissing() {
+        assertThatCode(() -> testee.deleteParts(BUCKET_NAME, BLOB_ID).block())
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    void selectRowCountShouldNotReturnDeletedData() {
+        testee.saveBlobPartsReferences(BUCKET_NAME, BLOB_ID, NUMBER_OF_CHUNK).block();
+
+        testee.deletePosition(BUCKET_NAME, BLOB_ID).block();
+
+        Optional<Integer> maybeRowCount = testee.selectRowCount(BUCKET_NAME, BLOB_ID).blockOptional();
+        assertThat(maybeRowCount).isEmpty();
+    }
+
+    @Test
+    void readPartShouldNotReturnDeletedItem() {
+        testee.writePart(ByteBuffer.wrap(DATA), BUCKET_NAME, BLOB_ID, POSITION).block();
+
+        testee.deleteParts(BUCKET_NAME, BLOB_ID).block();
+
+        Optional<byte[]> maybeBytes = testee.readPart(BUCKET_NAME, BLOB_ID, POSITION).blockOptional();
+        assertThat(maybeBytes).isEmpty();
+    }
+
+    @Test
+    void readPartShouldNotReturnDeletedItems() {
+        testee.writePart(ByteBuffer.wrap(DATA), BUCKET_NAME, BLOB_ID, POSITION).block();
+        testee.writePart(ByteBuffer.wrap(DATA), BUCKET_NAME, BLOB_ID, POSITION_2).block();
+
+        testee.deleteParts(BUCKET_NAME, BLOB_ID).block();
+
+        Optional<byte[]> maybeBytes = testee.readPart(BUCKET_NAME, BLOB_ID, POSITION).blockOptional();
+        Optional<byte[]> maybeBytes2 = testee.readPart(BUCKET_NAME, BLOB_ID, POSITION_2).blockOptional();
+        assertThat(maybeBytes).isEmpty();
+        assertThat(maybeBytes2).isEmpty();
+    }
+
+    @Test
     void readPartShouldReturnPreviouslySavedData() {
         testee.writePart(ByteBuffer.wrap(DATA), BUCKET_NAME, BLOB_ID, POSITION).block();
 
diff --git a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraDefaultBucketDAOTest.java b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraDefaultBucketDAOTest.java
index fb98630..01ffaab 100644
--- a/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraDefaultBucketDAOTest.java
+++ b/server/blob/blob-cassandra/src/test/java/org/apache/james/blob/cassandra/CassandraDefaultBucketDAOTest.java
@@ -27,6 +27,7 @@ import static org.apache.james.blob.cassandra.CassandraBlobStoreFixture.NUMBER_O
 import static org.apache.james.blob.cassandra.CassandraBlobStoreFixture.POSITION;
 import static org.apache.james.blob.cassandra.CassandraBlobStoreFixture.POSITION_2;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 
 import java.nio.ByteBuffer;
 import java.util.Optional;
@@ -108,4 +109,49 @@ class CassandraDefaultBucketDAOTest {
 
         assertThat(maybeRowCount).isEmpty();
     }
+
+    @Test
+    void deletePositionShouldNotThrowWhenMissing() {
+        assertThatCode(() -> testee.deletePosition(BLOB_ID).block())
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    void deletePartShouldNotThrowWhenMissing() {
+        assertThatCode(() -> testee.deleteParts(BLOB_ID).block())
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    void selectRowCountShouldNotReturnDeletedData() {
+        testee.saveBlobPartsReferences(BLOB_ID, NUMBER_OF_CHUNK).block();
+
+        testee.deletePosition(BLOB_ID).block();
+
+        Optional<Integer> maybeRowCount = testee.selectRowCount(BLOB_ID).blockOptional();
+        assertThat(maybeRowCount).isEmpty();
+    }
+
+    @Test
+    void readPartShouldNotReturnDeletedItem() {
+        testee.writePart(ByteBuffer.wrap(DATA), BLOB_ID, POSITION).block();
+
+        testee.deleteParts(BLOB_ID).block();
+
+        Optional<byte[]> maybeBytes = testee.readPart(BLOB_ID, POSITION).blockOptional();
+        assertThat(maybeBytes).isEmpty();
+    }
+
+    @Test
+    void readPartShouldNotReturnDeletedItems() {
+        testee.writePart(ByteBuffer.wrap(DATA), BLOB_ID, POSITION).block();
+        testee.writePart(ByteBuffer.wrap(DATA), BLOB_ID, POSITION_2).block();
+
+        testee.deleteParts(BLOB_ID).block();
+
+        Optional<byte[]> maybeBytes = testee.readPart(BLOB_ID, POSITION).blockOptional();
+        Optional<byte[]> maybeBytes2 = testee.readPart(BLOB_ID, POSITION_2).blockOptional();
+        assertThat(maybeBytes).isEmpty();
+        assertThat(maybeBytes2).isEmpty();
+    }
 }
\ No newline at end of file


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