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