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 03d0cf4b19c4efe4902e7c4ecf4409f61238de03 Author: Benoit Tellier <btell...@linagora.com> AuthorDate: Sun Apr 12 20:47:22 2020 +0700 JAMES-3148 Cleanup Deleted Messages DAO --- .../CassandraMailboxSessionMapperFactory.java | 2 +- .../mailbox/cassandra/DeleteMessageListener.java | 6 +++- .../cassandra/mail/CassandraDeletedMessageDAO.java | 13 ++++++++ .../cassandra/CassandraMailboxManagerTest.java | 35 ++++++++++++++++++++++ .../mail/CassandraDeletedMessageDAOTest.java | 20 +++++++++++++ 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java index 13a6d95..ba80ed4 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java @@ -205,6 +205,6 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa public DeleteMessageListener deleteMessageListener() { return new DeleteMessageListener(imapUidDAO, messageIdDAO, messageDAO, attachmentDAOV2, ownerDAO, - attachmentMessageIdDAO, aclMapper, userMailboxRightsDAO, applicableFlagDAO, firstUnseenDAO); + attachmentMessageIdDAO, aclMapper, userMailboxRightsDAO, applicableFlagDAO, firstUnseenDAO, deletedMessageDAO); } } diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/DeleteMessageListener.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/DeleteMessageListener.java index 7c24b4e..c0f74d9 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/DeleteMessageListener.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/DeleteMessageListener.java @@ -33,6 +33,7 @@ import org.apache.james.mailbox.cassandra.mail.CassandraApplicableFlagDAO; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraDeletedMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraFirstUnseenDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; @@ -69,13 +70,14 @@ public class DeleteMessageListener implements MailboxListener.GroupMailboxListen private final CassandraUserMailboxRightsDAO rightsDAO; private final CassandraApplicableFlagDAO applicableFlagDAO; private final CassandraFirstUnseenDAO firstUnseenDAO; + private final CassandraDeletedMessageDAO deletedMessageDAO; @Inject public DeleteMessageListener(CassandraMessageIdToImapUidDAO imapUidDAO, CassandraMessageIdDAO messageIdDAO, CassandraMessageDAO messageDAO, CassandraAttachmentDAOV2 attachmentDAO, CassandraAttachmentOwnerDAO ownerDAO, CassandraAttachmentMessageIdDAO attachmentMessageIdDAO, CassandraACLMapper aclMapper, CassandraUserMailboxRightsDAO rightsDAO, CassandraApplicableFlagDAO applicableFlagDAO, - CassandraFirstUnseenDAO firstUnseenDAO) { + CassandraFirstUnseenDAO firstUnseenDAO, CassandraDeletedMessageDAO deletedMessageDAO) { this.imapUidDAO = imapUidDAO; this.messageIdDAO = messageIdDAO; this.messageDAO = messageDAO; @@ -86,6 +88,7 @@ public class DeleteMessageListener implements MailboxListener.GroupMailboxListen this.rightsDAO = rightsDAO; this.applicableFlagDAO = applicableFlagDAO; this.firstUnseenDAO = firstUnseenDAO; + this.deletedMessageDAO = deletedMessageDAO; } @Override @@ -124,6 +127,7 @@ public class DeleteMessageListener implements MailboxListener.GroupMailboxListen .then(deleteAcl(mailboxId)) .then(applicableFlagDAO.delete(mailboxId)) .then(firstUnseenDAO.removeAll(mailboxId)) + .then(deletedMessageDAO.removeAll(mailboxId)) .block(); } } diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraDeletedMessageDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraDeletedMessageDAO.java index cfdebae..8e45984 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraDeletedMessageDAO.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraDeletedMessageDAO.java @@ -53,6 +53,7 @@ public class CassandraDeletedMessageDAO { private final CassandraAsyncExecutor cassandraAsyncExecutor; private final PreparedStatement addStatement; private final PreparedStatement deleteStatement; + private final PreparedStatement deleteAllStatement; private final PreparedStatement selectAllUidStatement; private final PreparedStatement selectOneUidStatement; @@ -65,6 +66,7 @@ public class CassandraDeletedMessageDAO { this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session); this.addStatement = prepareAddStatement(session); this.deleteStatement = prepareDeleteStatement(session); + this.deleteAllStatement = prepareDeleteAllStatement(session); this.selectAllUidStatement = prepareAllUidStatement(session); this.selectOneUidStatement = prepareOneUidStatement(session); this.selectBetweenUidStatement = prepareBetweenUidStatement(session); @@ -112,6 +114,12 @@ public class CassandraDeletedMessageDAO { .and(eq(UID, bindMarker(UID)))); } + private PreparedStatement prepareDeleteAllStatement(Session session) { + return session.prepare(delete() + .from(TABLE_NAME) + .where(eq(MAILBOX_ID, bindMarker(MAILBOX_ID)))); + } + private PreparedStatement prepareAddStatement(Session session) { return session.prepare(insertInto(TABLE_NAME) .value(MAILBOX_ID, bindMarker(MAILBOX_ID)) @@ -131,6 +139,11 @@ public class CassandraDeletedMessageDAO { .setLong(UID, uid.asLong())); } + public Mono<Void> removeAll(CassandraId cassandraId) { + return cassandraAsyncExecutor.executeVoid(deleteAllStatement.bind() + .setUUID(MAILBOX_ID, cassandraId.asUuid())); + } + public Flux<MessageUid> retrieveDeletedMessage(CassandraId cassandraId, MessageRange range) { return retrieveResultSetOfDeletedMessage(cassandraId, range) .flatMapMany(this::resultSetToFlux); diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java index 56d9221..5f78c72 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java @@ -45,6 +45,7 @@ import org.apache.james.mailbox.cassandra.mail.CassandraApplicableFlagDAO; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraDeletedMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraFirstUnseenDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; @@ -642,6 +643,40 @@ public class CassandraMailboxManagerTest extends MailboxManagerTest<CassandraMai .isEmpty(); } + @Test + void deleteMailboxShouldCleanUpDeletedMessages(CassandraCluster cassandraCluster) throws Exception { + inboxManager.appendMessage(MessageManager.AppendCommand.builder() + .withFlags(new Flags(Flags.Flag.DELETED)) + .build(ClassLoaderUtils.getSystemResourceAsByteArray("eml/emailWithOnlyAttachment.eml")), session); + + mailboxManager.deleteMailbox(inbox, session); + + assertThat(deletedMessageDAO(cassandraCluster).retrieveDeletedMessage((CassandraId) inboxId, MessageRange.all()) + .collectList().block()) + .isEmpty(); + } + + @Test + void deleteMailboxShouldCleanUpDeletedMessagesWhenFailure(CassandraCluster cassandraCluster) throws Exception { + inboxManager.appendMessage(MessageManager.AppendCommand.builder() + .withFlags(new Flags(Flags.Flag.DELETED)) + .build(ClassLoaderUtils.getSystemResourceAsByteArray("eml/emailWithOnlyAttachment.eml")), session); + + cassandraCluster.getConf().registerScenario(fail() + .times(1) + .whenQueryStartsWith("DELETE FROM messageDeleted WHERE mailboxId=:mailboxId;")); + + mailboxManager.deleteMailbox(inbox, session); + + assertThat(deletedMessageDAO(cassandraCluster).retrieveDeletedMessage((CassandraId) inboxId, MessageRange.all()) + .collectList().block()) + .isEmpty(); + } + + private CassandraDeletedMessageDAO deletedMessageDAO(CassandraCluster cassandraCluster) { + return new CassandraDeletedMessageDAO(cassandraCluster.getConf()); + } + private CassandraFirstUnseenDAO firstUnseenDAO(CassandraCluster cassandraCluster) { return new CassandraFirstUnseenDAO(cassandraCluster.getConf()); } diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraDeletedMessageDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraDeletedMessageDAOTest.java index 6197506..f3154fe 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraDeletedMessageDAOTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraDeletedMessageDAOTest.java @@ -20,6 +20,7 @@ package org.apache.james.mailbox.cassandra.mail; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import java.util.List; import java.util.UUID; @@ -76,6 +77,25 @@ class CassandraDeletedMessageDAOTest { } @Test + void retrieveDeletedMessageShouldNotReturnDeletedEntries() { + testee.addDeleted(MAILBOX_ID, UID_1).block(); + testee.addDeleted(MAILBOX_ID, UID_2).block(); + + testee.removeAll(MAILBOX_ID).block(); + + List<MessageUid> result = testee.retrieveDeletedMessage(MAILBOX_ID, MessageRange.all()) + .collectList() + .block(); + + assertThat(result).isEmpty(); + } + + @Test + void removeAllShouldNotThrowWhenEmpty() { + assertThatCode(() -> testee.removeAll(MAILBOX_ID).block()).doesNotThrowAnyException(); + } + + @Test void addDeletedMessageShouldBeIdempotent() { testee.addDeleted(MAILBOX_ID, UID_1).block(); testee.addDeleted(MAILBOX_ID, UID_1).block(); --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org