JAMES-1874 Cassandra optimization : Add a table for recent messages
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/c8c12826 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/c8c12826 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/c8c12826 Branch: refs/heads/master Commit: c8c12826015ac8706d75d7d423aea5f38cc146c4 Parents: 9c28aad Author: Benoit Tellier <btell...@linagora.com> Authored: Fri Feb 3 19:41:02 2017 +0700 Committer: Benoit Tellier <btell...@linagora.com> Committed: Tue Feb 7 08:57:46 2017 +0700 ---------------------------------------------------------------------- .../CassandraMailboxSessionMapperFactory.java | 15 ++- .../mail/CassandraMailboxCounterDAO.java | 3 + .../mail/CassandraMailboxRecentsDAO.java | 105 ++++++++++++++++++ .../mail/CassandraMessageIdMapper.java | 29 +++-- .../cassandra/mail/CassandraMessageMapper.java | 55 +++++++--- .../modules/CassandraMailboxRecentsModule.java | 68 ++++++++++++ .../table/CassandraMailboxRecentsTable.java | 26 +++++ .../cassandra/CassandraMailboxManagerTest.java | 11 +- .../CassandraSubscriptionManagerTest.java | 8 +- .../cassandra/CassandraTestSystemFixture.java | 10 +- .../CassandraMailboxManagerAttachmentTest.java | 6 +- .../mail/CassandraMailboxRecentDAOTest.java | 107 +++++++++++++++++++ .../cassandra/mail/CassandraMapperProvider.java | 6 +- .../cassandra/host/CassandraHostSystem.java | 8 +- .../modules/mailbox/CassandraMailboxModule.java | 1 + 15 files changed, 428 insertions(+), 30 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java ---------------------------------------------------------------------- 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 e3ce7c7..b384297 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 @@ -27,6 +27,7 @@ import org.apache.james.mailbox.cassandra.mail.CassandraAnnotationMapper; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMapper; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxCounterDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMailboxMapper; +import org.apache.james.mailbox.cassandra.mail.CassandraMailboxRecentsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdMapper; @@ -59,20 +60,24 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa private final CassandraMessageDAO messageDAO; private final CassandraMessageIdDAO messageIdDAO; private final CassandraMessageIdToImapUidDAO imapUidDAO; - private CassandraMailboxCounterDAO mailboxCounterDAO; + private final CassandraMailboxCounterDAO mailboxCounterDAO; + private final CassandraMailboxRecentsDAO mailboxRecentsDAO; private int maxRetry; + @Inject public CassandraMailboxSessionMapperFactory(UidProvider uidProvider, ModSeqProvider modSeqProvider, Session session, CassandraTypesProvider typesProvider, - CassandraMessageDAO messageDAO, CassandraMessageIdDAO messageIdDAO, CassandraMessageIdToImapUidDAO imapUidDAO) { + CassandraMessageDAO messageDAO, CassandraMessageIdDAO messageIdDAO, CassandraMessageIdToImapUidDAO imapUidDAO, + CassandraMailboxCounterDAO mailboxCounterDAO, CassandraMailboxRecentsDAO mailboxRecentsDAO) { this.uidProvider = uidProvider; this.modSeqProvider = modSeqProvider; this.session = session; this.messageDAO = messageDAO; this.messageIdDAO = messageIdDAO; this.imapUidDAO = imapUidDAO; - this.mailboxCounterDAO = new CassandraMailboxCounterDAO(session); + this.mailboxCounterDAO = mailboxCounterDAO; + this.mailboxRecentsDAO = mailboxRecentsDAO; this.maxRetry = DEFAULT_MAX_RETRY; this.typesProvider = typesProvider; } @@ -84,13 +89,13 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa @Override public CassandraMessageMapper createMessageMapper(MailboxSession mailboxSession) { return new CassandraMessageMapper(uidProvider, modSeqProvider, null, maxRetry, createAttachmentMapper(mailboxSession), - messageDAO, messageIdDAO, imapUidDAO, mailboxCounterDAO); + messageDAO, messageIdDAO, imapUidDAO, mailboxCounterDAO, mailboxRecentsDAO); } @Override public MessageIdMapper createMessageIdMapper(MailboxSession mailboxSession) throws MailboxException { return new CassandraMessageIdMapper(getMailboxMapper(mailboxSession), getAttachmentMapper(mailboxSession), - imapUidDAO, messageIdDAO, messageDAO, mailboxCounterDAO, modSeqProvider, mailboxSession); + imapUidDAO, messageIdDAO, messageDAO, mailboxCounterDAO, mailboxRecentsDAO, modSeqProvider, mailboxSession); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxCounterDAO.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxCounterDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxCounterDAO.java index 32a1fee..7f3c35a 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxCounterDAO.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxCounterDAO.java @@ -29,6 +29,8 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.update; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import javax.inject.Inject; + import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor; import org.apache.james.mailbox.cassandra.CassandraId; import org.apache.james.mailbox.cassandra.table.CassandraMailboxCountersTable; @@ -49,6 +51,7 @@ public class CassandraMailboxCounterDAO { private final PreparedStatement decrementUnseenCountStatement; private final PreparedStatement decrementMessageCountStatement; + @Inject public CassandraMailboxCounterDAO(Session session) { cassandraAsyncExecutor = new CassandraAsyncExecutor(session); readStatement = createReadStatement(session); http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxRecentsDAO.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxRecentsDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxRecentsDAO.java new file mode 100644 index 0000000..06df836 --- /dev/null +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxRecentsDAO.java @@ -0,0 +1,105 @@ +/**************************************************************** + * 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.mailbox.cassandra.mail; + +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; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import javax.inject.Inject; + +import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor; +import org.apache.james.backends.cassandra.utils.CassandraUtils; +import org.apache.james.mailbox.MessageUid; +import org.apache.james.mailbox.cassandra.CassandraId; +import org.apache.james.mailbox.cassandra.table.CassandraMailboxRecentsTable; + +import com.datastax.driver.core.BoundStatement; +import com.datastax.driver.core.PreparedStatement; +import com.datastax.driver.core.Session; +import com.github.steveash.guavate.Guavate; + +public class CassandraMailboxRecentsDAO { + + private final CassandraAsyncExecutor cassandraAsyncExecutor; + private final PreparedStatement readStatement; + private final PreparedStatement deleteStatement; + private final PreparedStatement addStatement; + + @Inject + public CassandraMailboxRecentsDAO(Session session) { + cassandraAsyncExecutor = new CassandraAsyncExecutor(session); + readStatement = createReadStatement(session); + deleteStatement = createDeleteStatement(session); + addStatement = createAddStatement(session); + } + + private PreparedStatement createReadStatement(Session session) { + return session.prepare( + select(CassandraMailboxRecentsTable.RECENT_MESSAGE_UID) + .from(CassandraMailboxRecentsTable.TABLE_NAME) + .where(eq(CassandraMailboxRecentsTable.MAILBOX_ID, bindMarker(CassandraMailboxRecentsTable.MAILBOX_ID)))); + } + + private PreparedStatement createDeleteStatement(Session session) { + return session.prepare( + delete() + .from(CassandraMailboxRecentsTable.TABLE_NAME) + .where(eq(CassandraMailboxRecentsTable.MAILBOX_ID, bindMarker(CassandraMailboxRecentsTable.MAILBOX_ID))) + .and(eq(CassandraMailboxRecentsTable.RECENT_MESSAGE_UID, bindMarker(CassandraMailboxRecentsTable.RECENT_MESSAGE_UID)))); + } + + private PreparedStatement createAddStatement(Session session) { + return session.prepare( + insertInto(CassandraMailboxRecentsTable.TABLE_NAME) + .value(CassandraMailboxRecentsTable.MAILBOX_ID, bindMarker(CassandraMailboxRecentsTable.MAILBOX_ID)) + .value(CassandraMailboxRecentsTable.RECENT_MESSAGE_UID, bindMarker(CassandraMailboxRecentsTable.RECENT_MESSAGE_UID))); + } + + public CompletableFuture<List<MessageUid>> getRecentMessageUidsInMailbox(CassandraId mailboxId) { + return cassandraAsyncExecutor.execute(bindWithMailbox(mailboxId, readStatement)) + .thenApply(CassandraUtils::convertToStream) + .thenApply(stream -> stream.map(row -> row.getLong(CassandraMailboxRecentsTable.RECENT_MESSAGE_UID))) + .thenApply(stream -> stream.map(MessageUid::of)) + .thenApply(stream -> stream.collect(Guavate.toImmutableList())); + } + + private BoundStatement bindWithMailbox(CassandraId mailboxId, PreparedStatement statement) { + return statement.bind() + .setUUID(CassandraMailboxRecentsTable.MAILBOX_ID, mailboxId.asUuid()); + } + + public CompletableFuture<Void> removeFromRecent(CassandraId mailboxId, MessageUid messageUid) { + return cassandraAsyncExecutor.executeVoid(deleteStatement.bind() + .setUUID(CassandraMailboxRecentsTable.MAILBOX_ID, mailboxId.asUuid()) + .setLong(CassandraMailboxRecentsTable.RECENT_MESSAGE_UID, messageUid.asLong())); + } + + public CompletableFuture<Void> addToRecent(CassandraId mailboxId, MessageUid messageUid) { + return cassandraAsyncExecutor.executeVoid(addStatement.bind() + .setUUID(CassandraMailboxRecentsTable.MAILBOX_ID, mailboxId.asUuid()) + .setLong(CassandraMailboxRecentsTable.RECENT_MESSAGE_UID, messageUid.asLong())); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java index b4e0474..41d8749 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java @@ -69,18 +69,20 @@ public class CassandraMessageIdMapper implements MessageIdMapper { private final CassandraMessageIdDAO messageIdDAO; private final CassandraMessageDAO messageDAO; private final CassandraMailboxCounterDAO mailboxCounterDAO; + private final CassandraMailboxRecentsDAO mailboxRecentsDAO; private final ModSeqProvider modSeqProvider; private final MailboxSession mailboxSession; public CassandraMessageIdMapper(MailboxMapper mailboxMapper, AttachmentMapper attachmentMapper, CassandraMessageIdToImapUidDAO imapUidDAO, CassandraMessageIdDAO messageIdDAO, CassandraMessageDAO messageDAO, - CassandraMailboxCounterDAO cassandraMailboxCounterDAO, ModSeqProvider modSeqProvider, MailboxSession mailboxSession) { + CassandraMailboxCounterDAO cassandraMailboxCounterDAO, CassandraMailboxRecentsDAO mailboxRecentsDAO, ModSeqProvider modSeqProvider, MailboxSession mailboxSession) { this.mailboxMapper = mailboxMapper; this.attachmentMapper = attachmentMapper; this.imapUidDAO = imapUidDAO; this.messageIdDAO = messageIdDAO; this.messageDAO = messageDAO; this.mailboxCounterDAO = cassandraMailboxCounterDAO; + this.mailboxRecentsDAO = mailboxRecentsDAO; this.modSeqProvider = modSeqProvider; this.mailboxSession = mailboxSession; } @@ -149,6 +151,7 @@ public class CassandraMessageIdMapper implements MessageIdMapper { imapUidDAO.insert(composedMessageIdWithMetaData), messageIdDAO.insert(composedMessageIdWithMetaData))) .thenCompose(voidValue -> CompletableFuture.allOf( + mailboxRecentsDAO.addToRecent(mailboxId, mailboxMessage.getUid()), mailboxCounterDAO.incrementCount(mailboxId), incrementUnseenOnSave(mailboxId, mailboxMessage.createFlags()))) .join(); @@ -196,6 +199,7 @@ public class CassandraMessageIdMapper implements MessageIdMapper { messageIdDAO.delete(mailboxId, metaData.getComposedMessageId().getUid())) .thenCompose(voidValue -> CompletableFuture.allOf( mailboxCounterDAO.decrementCount(mailboxId), + mailboxRecentsDAO.removeFromRecent(mailboxId, metaData.getComposedMessageId().getUid()), decrementUnseenOnDelete(mailboxId, metaData.getFlags()))); } @@ -243,20 +247,31 @@ public class CassandraMessageIdMapper implements MessageIdMapper { private CompletableFuture<Pair<MailboxId, UpdatedFlags>> updateCounts(Pair<MailboxId, UpdatedFlags> pair) { CassandraId cassandraId = (CassandraId) pair.getLeft(); return CompletableFuture.allOf( - incrementCountIfNeeded(pair.getRight().getOldFlags(), pair.getRight().getNewFlags(), cassandraId), - decrementCountIfNeeded(pair.getRight().getOldFlags(), pair.getRight().getNewFlags(), cassandraId)) + manageRecent(pair.getRight(), cassandraId), + incrementCountIfNeeded(pair.getRight(), cassandraId), + decrementCountIfNeeded(pair.getRight(), cassandraId)) .thenApply(voidValue -> pair); } - private CompletableFuture<Void> incrementCountIfNeeded(Flags oldFlags, Flags newFlags, CassandraId cassandraId) { - if (oldFlags.contains(Flags.Flag.SEEN) && !newFlags.contains(Flags.Flag.SEEN)) { + private CompletableFuture<Void> manageRecent(UpdatedFlags updatedFlags, CassandraId cassandraId) { + if (updatedFlags.isSet(Flags.Flag.RECENT)) { + return mailboxRecentsDAO.addToRecent(cassandraId, updatedFlags.getUid()); + } + if (updatedFlags.isUnset(Flags.Flag.RECENT)){ + return mailboxRecentsDAO.removeFromRecent(cassandraId, updatedFlags.getUid()); + } + return CompletableFuture.completedFuture(null); + } + + private CompletableFuture<Void> incrementCountIfNeeded(UpdatedFlags updatedFlags, CassandraId cassandraId) { + if (updatedFlags.isUnset(Flags.Flag.SEEN)) { return mailboxCounterDAO.incrementUnseen(cassandraId); } return CompletableFuture.completedFuture(null); } - private CompletableFuture<Void> decrementCountIfNeeded(Flags oldFlags, Flags newFlags, CassandraId cassandraId) { - if (!oldFlags.contains(Flags.Flag.SEEN) && newFlags.contains(Flags.Flag.SEEN)) { + private CompletableFuture<Void> decrementCountIfNeeded(UpdatedFlags updatedFlags, CassandraId cassandraId) { + if (updatedFlags.isSet(Flags.Flag.SEEN)) { return mailboxCounterDAO.decrementUnseen(cassandraId); } return CompletableFuture.completedFuture(null); http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java index 79763ee..38d27b8 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java @@ -75,10 +75,12 @@ public class CassandraMessageMapper implements MessageMapper { private final CassandraMessageIdDAO messageIdDAO; private final CassandraMessageIdToImapUidDAO imapUidDAO; private final CassandraMailboxCounterDAO mailboxCounterDAO; + private final CassandraMailboxRecentsDAO mailboxRecentDAO; public CassandraMessageMapper(UidProvider uidProvider, ModSeqProvider modSeqProvider, MailboxSession mailboxSession, int maxRetries, AttachmentMapper attachmentMapper, - CassandraMessageDAO messageDAO, CassandraMessageIdDAO messageIdDAO, CassandraMessageIdToImapUidDAO imapUidDAO, CassandraMailboxCounterDAO mailboxCounterDAO) { + CassandraMessageDAO messageDAO, CassandraMessageIdDAO messageIdDAO, CassandraMessageIdToImapUidDAO imapUidDAO, + CassandraMailboxCounterDAO mailboxCounterDAO, CassandraMailboxRecentsDAO mailboxRecentDAO) { this.uidProvider = uidProvider; this.modSeqProvider = modSeqProvider; this.mailboxSession = mailboxSession; @@ -88,6 +90,7 @@ public class CassandraMessageMapper implements MessageMapper { this.messageIdDAO = messageIdDAO; this.imapUidDAO = imapUidDAO; this.mailboxCounterDAO = mailboxCounterDAO; + this.mailboxRecentDAO = mailboxRecentDAO; } @Override @@ -123,6 +126,7 @@ public class CassandraMessageMapper implements MessageMapper { imapUidDAO.delete(messageId, mailboxId), messageIdDAO.delete(mailboxId, uid) ).thenCompose(voidValue -> CompletableFuture.allOf( + removeRecentOnDelete(mailboxId, composedMessageIdWithMetaData.getFlags(), composedMessageId.getUid()), mailboxCounterDAO.decrementCount(mailboxId), decrementUnseenOnDelete(mailboxId, composedMessageIdWithMetaData.getFlags()))); } @@ -134,6 +138,14 @@ public class CassandraMessageMapper implements MessageMapper { return mailboxCounterDAO.decrementUnseen(mailboxId); } + private CompletableFuture<Void> removeRecentOnDelete(CassandraId mailboxId, Flags flags, MessageUid uid) { + if (flags.contains(Flag.RECENT)) { + return mailboxRecentDAO.removeFromRecent(mailboxId, uid); + } + return CompletableFuture.completedFuture(null); + } + + private CompletableFuture<Optional<ComposedMessageIdWithMetaData>> retrieveMessageId(CassandraId mailboxId, MailboxMessage message) { return messageIdDAO.retrieve(mailboxId, message.getUid()); } @@ -167,13 +179,8 @@ public class CassandraMessageMapper implements MessageMapper { @Override public List<MessageUid> findRecentMessageUidsInMailbox(Mailbox mailbox) throws MailboxException { CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); - return retrieveMessages(retrieveMessageIds(mailboxId, MessageRange.all()), FetchType.Metadata, Optional.empty()) - .filter(MailboxMessage::isRecent) - .flatMap(message -> imapUidDAO.retrieve((CassandraMessageId) message.getMessageId(), Optional.ofNullable(mailboxId)).join()) - .map(ComposedMessageIdWithMetaData::getComposedMessageId) - .map(ComposedMessageId::getUid) - .sorted() - .collect(Collectors.toList()); + return mailboxRecentDAO.getRecentMessageUidsInMailbox(mailboxId) + .join(); } @Override @@ -225,6 +232,7 @@ public class CassandraMessageMapper implements MessageMapper { CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); save(mailbox, message) .thenCompose(voidValue -> CompletableFuture.allOf( + addRecentOnSave(mailboxId, message), incrementUnseenOnSave(mailboxId, message.createFlags()), mailboxCounterDAO.incrementCount(mailboxId))) .join(); @@ -238,12 +246,19 @@ public class CassandraMessageMapper implements MessageMapper { return mailboxCounterDAO.incrementUnseen(mailboxId); } + private CompletableFuture<Void> addRecentOnSave(CassandraId mailboxId, MailboxMessage message) { + if (message.createFlags().contains(Flag.RECENT)) { + return mailboxRecentDAO.addToRecent(mailboxId, message.getUid()); + } + return CompletableFuture.completedFuture(null); + } + @Override public Iterator<UpdatedFlags> updateFlags(Mailbox mailbox, FlagsUpdateCalculator flagUpdateCalculator, MessageRange set) throws MailboxException { CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); return retrieveMessages(retrieveMessageIds(mailboxId, set), FetchType.Metadata, Optional.empty()) .flatMap(message -> updateFlagsOnMessage(mailbox, flagUpdateCalculator, message)) - .map((UpdatedFlags updatedFlags) -> manageUnseenMessageCounts(mailbox, updatedFlags.getOldFlags(), updatedFlags.getNewFlags()) + .map((UpdatedFlags updatedFlags) -> manageCounters(mailbox, updatedFlags) .thenApply(voidValue -> updatedFlags)) .map(CompletableFuture::join) .collect(Collectors.toList()) // This collect is here as we need to consume all the stream before returning result @@ -282,17 +297,33 @@ public class CassandraMessageMapper implements MessageMapper { imapUidDAO.insert(composedMessageIdWithMetaData)); } - private CompletableFuture<Void> manageUnseenMessageCounts(Mailbox mailbox, Flags oldFlags, Flags newFlags) { + private CompletableFuture<Void> manageCounters(Mailbox mailbox, UpdatedFlags updatedFlags) { + return CompletableFuture.allOf(manageUnseenMessageCounts(mailbox, updatedFlags), + manageRecents(mailbox, updatedFlags)); + } + + private CompletableFuture<Void> manageUnseenMessageCounts(Mailbox mailbox, UpdatedFlags updatedFlags) { CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); - if (oldFlags.contains(Flag.SEEN) && !newFlags.contains(Flag.SEEN)) { + if (updatedFlags.isUnset(Flag.SEEN)) { return mailboxCounterDAO.incrementUnseen(mailboxId); } - if (!oldFlags.contains(Flag.SEEN) && newFlags.contains(Flag.SEEN)) { + if (updatedFlags.isSet(Flag.SEEN)) { return mailboxCounterDAO.decrementUnseen(mailboxId); } return CompletableFuture.completedFuture(null); } + private CompletableFuture<Void> manageRecents(Mailbox mailbox, UpdatedFlags updatedFlags) { + CassandraId mailboxId = (CassandraId) mailbox.getMailboxId(); + if (updatedFlags.isUnset(Flag.RECENT)) { + return mailboxRecentDAO.removeFromRecent(mailboxId, updatedFlags.getUid()); + } + if (updatedFlags.isSet(Flag.RECENT)) { + return mailboxRecentDAO.addToRecent(mailboxId, updatedFlags.getUid()); + } + return CompletableFuture.completedFuture(null); + } + private Stream<UpdatedFlags> updateFlagsOnMessage(Mailbox mailbox, FlagsUpdateCalculator flagUpdateCalculator, MailboxMessage message) { return tryMessageFlagsUpdate(flagUpdateCalculator, mailbox, message) .map(Stream::of) http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMailboxRecentsModule.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMailboxRecentsModule.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMailboxRecentsModule.java new file mode 100644 index 0000000..6cccbd8 --- /dev/null +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraMailboxRecentsModule.java @@ -0,0 +1,68 @@ +/**************************************************************** + * 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.mailbox.cassandra.modules; + +import static com.datastax.driver.core.DataType.bigint; +import static com.datastax.driver.core.DataType.list; +import static com.datastax.driver.core.DataType.timeuuid; + +import java.util.Collections; +import java.util.List; + +import org.apache.james.backends.cassandra.components.CassandraIndex; +import org.apache.james.backends.cassandra.components.CassandraModule; +import org.apache.james.backends.cassandra.components.CassandraTable; +import org.apache.james.backends.cassandra.components.CassandraType; +import org.apache.james.mailbox.cassandra.table.CassandraMailboxRecentsTable; + +import com.datastax.driver.core.schemabuilder.SchemaBuilder; + +public class CassandraMailboxRecentsModule implements CassandraModule { + + private final List<CassandraTable> tables; + private final List<CassandraIndex> index; + private final List<CassandraType> types; + + public CassandraMailboxRecentsModule() { + tables = Collections.singletonList( + new CassandraTable(CassandraMailboxRecentsTable.TABLE_NAME, + SchemaBuilder.createTable(CassandraMailboxRecentsTable.TABLE_NAME) + .ifNotExists() + .addPartitionKey(CassandraMailboxRecentsTable.MAILBOX_ID, timeuuid()) + .addClusteringColumn(CassandraMailboxRecentsTable.RECENT_MESSAGE_UID, bigint()))); + index = Collections.emptyList(); + types = Collections.emptyList(); + } + + @Override + public List<CassandraTable> moduleTables() { + return tables; + } + + @Override + public List<CassandraIndex> moduleIndex() { + return index; + } + + @Override + public List<CassandraType> moduleTypes() { + return types; + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxRecentsTable.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxRecentsTable.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxRecentsTable.java new file mode 100644 index 0000000..d729ae4 --- /dev/null +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMailboxRecentsTable.java @@ -0,0 +1,26 @@ +/**************************************************************** + * 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.mailbox.cassandra.table; + +public interface CassandraMailboxRecentsTable { + String TABLE_NAME = "mailboxRecents"; + String MAILBOX_ID = "mailboxId"; + String RECENT_MESSAGE_UID = "recent_mesage_uid"; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java ---------------------------------------------------------------------- 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 633bfbc..caadf4b 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 @@ -24,6 +24,8 @@ import org.apache.james.mailbox.acl.GroupMembershipResolver; import org.apache.james.mailbox.acl.MailboxACLResolver; import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver; import org.apache.james.mailbox.acl.UnionMailboxACLResolver; +import org.apache.james.mailbox.cassandra.mail.CassandraMailboxCounterDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMailboxRecentsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO; @@ -34,6 +36,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule; +import org.apache.james.mailbox.cassandra.modules.CassandraMailboxRecentsModule; import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraModSeqModule; import org.apache.james.mailbox.cassandra.modules.CassandraSubscriptionModule; @@ -60,6 +63,7 @@ public class CassandraMailboxManagerTest { new CassandraMailboxModule(), new CassandraMessageModule(), new CassandraMailboxCounterModule(), + new CassandraMailboxRecentsModule(), new CassandraUidModule(), new CassandraModSeqModule(), new CassandraSubscriptionModule(), @@ -77,13 +81,18 @@ public class CassandraMailboxManagerTest { CassandraMessageIdDAO messageIdDAO = new CassandraMessageIdDAO(CASSANDRA.getConf(), messageIdFactory); CassandraMessageIdToImapUidDAO imapUidDAO = new CassandraMessageIdToImapUidDAO(CASSANDRA.getConf(), messageIdFactory); CassandraMessageDAO messageDAO = new CassandraMessageDAO(CASSANDRA.getConf(), CASSANDRA.getTypesProvider(), messageIdFactory); + CassandraMailboxCounterDAO mailboxCounterDAO = new CassandraMailboxCounterDAO(CASSANDRA.getConf()); + CassandraMailboxRecentsDAO mailboxRecentsDAO = new CassandraMailboxRecentsDAO(CASSANDRA.getConf()); + CassandraMailboxSessionMapperFactory mapperFactory = new CassandraMailboxSessionMapperFactory(uidProvider, modSeqProvider, CASSANDRA.getConf(), CASSANDRA.getTypesProvider(), messageDAO, messageIdDAO, - imapUidDAO); + imapUidDAO, + mailboxCounterDAO, + mailboxRecentsDAO); MailboxACLResolver aclResolver = new UnionMailboxACLResolver(); GroupMembershipResolver groupMembershipResolver = new SimpleGroupMembershipResolver(); http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java index f253f53..5d5e6c1 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java @@ -23,6 +23,8 @@ import org.apache.james.backends.cassandra.CassandraCluster; import org.apache.james.backends.cassandra.init.CassandraModuleComposite; import org.apache.james.mailbox.AbstractSubscriptionManagerTest; import org.apache.james.mailbox.SubscriptionManager; +import org.apache.james.mailbox.cassandra.mail.CassandraMailboxCounterDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMailboxRecentsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO; @@ -45,6 +47,8 @@ public class CassandraSubscriptionManagerTest extends AbstractSubscriptionManage CassandraMessageIdToImapUidDAO imapUidDAO = null; CassandraMessageDAO messageDAO = null; CassandraMessageIdDAO messageIdDAO = null; + CassandraMailboxCounterDAO mailboxCounterDAO = null; + CassandraMailboxRecentsDAO mailboxRecentsDAO = null; return new CassandraSubscriptionManager( new CassandraMailboxSessionMapperFactory( new CassandraUidProvider(cassandra.getConf()), @@ -53,7 +57,9 @@ public class CassandraSubscriptionManagerTest extends AbstractSubscriptionManage cassandra.getTypesProvider(), messageDAO, messageIdDAO, - imapUidDAO + imapUidDAO, + mailboxCounterDAO, + mailboxRecentsDAO ) ); } http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java index fdf3abe..0999c8e 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java @@ -23,6 +23,8 @@ import static org.mockito.Mockito.mock; import org.apache.james.backends.cassandra.CassandraCluster; import org.apache.james.backends.cassandra.init.CassandraModuleComposite; +import org.apache.james.mailbox.cassandra.mail.CassandraMailboxCounterDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMailboxRecentsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO; @@ -33,6 +35,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule; +import org.apache.james.mailbox.cassandra.modules.CassandraMailboxRecentsModule; import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraModSeqModule; import org.apache.james.mailbox.cassandra.modules.CassandraUidModule; @@ -50,6 +53,7 @@ public class CassandraTestSystemFixture { new CassandraMailboxModule(), new CassandraMessageModule(), new CassandraMailboxCounterModule(), + new CassandraMailboxRecentsModule(), new CassandraUidModule(), new CassandraModSeqModule(), new CassandraAttachmentModule(), @@ -64,13 +68,17 @@ public class CassandraTestSystemFixture { CassandraMessageIdDAO messageIdDAO = new CassandraMessageIdDAO(CASSANDRA.getConf(), messageIdFactory); CassandraMessageIdToImapUidDAO imapUidDAO = new CassandraMessageIdToImapUidDAO(CASSANDRA.getConf(), messageIdFactory); CassandraMessageDAO messageDAO = new CassandraMessageDAO(CASSANDRA.getConf(), CASSANDRA.getTypesProvider(), messageIdFactory); + CassandraMailboxCounterDAO mailboxCounterDAO = new CassandraMailboxCounterDAO(CASSANDRA.getConf()); + CassandraMailboxRecentsDAO mailboxRecentsDAO = new CassandraMailboxRecentsDAO(CASSANDRA.getConf()); return new CassandraMailboxSessionMapperFactory(uidProvider, modSeqProvider, CASSANDRA.getConf(), CASSANDRA.getTypesProvider(), messageDAO, messageIdDAO, - imapUidDAO); + imapUidDAO, + mailboxCounterDAO, + mailboxRecentsDAO); } public static CassandraMailboxManager createMailboxManager(CassandraMailboxSessionMapperFactory mapperFactory) throws Exception{ http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java index b923c1f..93228aa 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java @@ -32,6 +32,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAclModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule; +import org.apache.james.mailbox.cassandra.modules.CassandraMailboxRecentsModule; import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraModSeqModule; import org.apache.james.mailbox.cassandra.modules.CassandraUidModule; @@ -47,6 +48,7 @@ public class CassandraMailboxManagerAttachmentTest extends AbstractMailboxManage new CassandraMailboxModule(), new CassandraMessageModule(), new CassandraMailboxCounterModule(), + new CassandraMailboxRecentsModule(), new CassandraModSeqModule(), new CassandraUidModule(), new CassandraAttachmentModule())); @@ -64,7 +66,9 @@ public class CassandraMailboxManagerAttachmentTest extends AbstractMailboxManage cassandra.getTypesProvider(), new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider(), messageIdFactory), new CassandraMessageIdDAO(cassandra.getConf(), messageIdFactory), - new CassandraMessageIdToImapUidDAO(cassandra.getConf(), messageIdFactory)); + new CassandraMessageIdToImapUidDAO(cassandra.getConf(), messageIdFactory), + new CassandraMailboxCounterDAO(cassandra.getConf()), + new CassandraMailboxRecentsDAO(cassandra.getConf())); Authenticator noAuthenticator = null; mailboxManager = new CassandraMailboxManager(mailboxSessionMapperFactory, noAuthenticator, new NoMailboxPathLocker(), new MessageParser(), messageIdFactory); mailboxManager.init(); http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxRecentDAOTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxRecentDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxRecentDAOTest.java new file mode 100644 index 0000000..81bb313 --- /dev/null +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxRecentDAOTest.java @@ -0,0 +1,107 @@ +/**************************************************************** + * 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.mailbox.cassandra.mail; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.james.backends.cassandra.CassandraCluster; +import org.apache.james.mailbox.MessageUid; +import org.apache.james.mailbox.cassandra.CassandraId; +import org.apache.james.mailbox.cassandra.modules.CassandraMailboxRecentsModule; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class CassandraMailboxRecentDAOTest { + public static final MessageUid UID1 = MessageUid.of(36L); + public static final MessageUid UID2 = MessageUid.of(37L); + public static final CassandraId CASSANDRA_ID = CassandraId.timeBased(); + + private CassandraCluster cassandra; + private CassandraMailboxRecentsDAO testee; + + @Before + public void setUp() { + cassandra = CassandraCluster.create(new CassandraMailboxRecentsModule()); + cassandra.ensureAllTables(); + + testee = new CassandraMailboxRecentsDAO(cassandra.getConf()); + } + + @After + public void tearDown() { + cassandra.clearAllTables(); + } + + @Test + public void getRecentMessageUidsInMailboxShouldBeEmptyByDefault() throws Exception { + assertThat(testee.getRecentMessageUidsInMailbox(CASSANDRA_ID).join()).isEmpty(); + } + + @Test + public void addToRecentShouldAddUidWhenEmpty() throws Exception { + testee.addToRecent(CASSANDRA_ID, UID1).join(); + + assertThat(testee.getRecentMessageUidsInMailbox(CASSANDRA_ID).join()).containsOnly(UID1); + } + + @Test + public void removeFromRecentShouldRemoveUidWhenOnlyOneUid() throws Exception { + testee.addToRecent(CASSANDRA_ID, UID1).join(); + + testee.removeFromRecent(CASSANDRA_ID, UID1).join(); + + assertThat(testee.getRecentMessageUidsInMailbox(CASSANDRA_ID).join()).isEmpty(); + } + + @Test + public void removeFromRecentShouldNotFailIfNotExisting() throws Exception { + testee.removeFromRecent(CASSANDRA_ID, UID1).join(); + + assertThat(testee.getRecentMessageUidsInMailbox(CASSANDRA_ID).join()).isEmpty(); + } + + @Test + public void addToRecentShouldAddUidWhenNotEmpty() throws Exception { + testee.addToRecent(CASSANDRA_ID, UID1).join(); + + testee.addToRecent(CASSANDRA_ID, UID2).join(); + + assertThat(testee.getRecentMessageUidsInMailbox(CASSANDRA_ID).join()).containsOnly(UID1, UID2); + } + + @Test + public void removeFromRecentShouldOnlyRemoveUidWhenNotEmpty() throws Exception { + testee.addToRecent(CASSANDRA_ID, UID1).join(); + testee.addToRecent(CASSANDRA_ID, UID2).join(); + + testee.removeFromRecent(CASSANDRA_ID, UID2).join(); + + assertThat(testee.getRecentMessageUidsInMailbox(CASSANDRA_ID).join()).containsOnly(UID1); + } + + @Test + public void addToRecentShouldBeIdempotent() throws Exception { + testee.addToRecent(CASSANDRA_ID, UID1).join(); + testee.addToRecent(CASSANDRA_ID, UID1).join(); + + assertThat(testee.getRecentMessageUidsInMailbox(CASSANDRA_ID).join()).containsOnly(UID1); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMapperProvider.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMapperProvider.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMapperProvider.java index 2516944..ba39d49 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMapperProvider.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMapperProvider.java @@ -33,6 +33,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule; +import org.apache.james.mailbox.cassandra.modules.CassandraMailboxRecentsModule; import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraModSeqModule; import org.apache.james.mailbox.cassandra.modules.CassandraUidModule; @@ -59,6 +60,7 @@ public class CassandraMapperProvider implements MapperProvider { new CassandraMailboxModule(), new CassandraMessageModule(), new CassandraMailboxCounterModule(), + new CassandraMailboxRecentsModule(), new CassandraModSeqModule(), new CassandraUidModule(), new CassandraAttachmentModule(), @@ -100,7 +102,9 @@ public class CassandraMapperProvider implements MapperProvider { cassandra.getTypesProvider(), new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider(), MESSAGE_ID_FACTORY), new CassandraMessageIdDAO(cassandra.getConf(), MESSAGE_ID_FACTORY), - new CassandraMessageIdToImapUidDAO(cassandra.getConf(), MESSAGE_ID_FACTORY)); + new CassandraMessageIdToImapUidDAO(cassandra.getConf(), MESSAGE_ID_FACTORY), + new CassandraMailboxCounterDAO(cassandra.getConf()), + new CassandraMailboxRecentsDAO(cassandra.getConf())); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java ---------------------------------------------------------------------- diff --git a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java index 16ef829..3b8b46c 100644 --- a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java +++ b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java @@ -29,6 +29,8 @@ import org.apache.james.mailbox.SubscriptionManager; import org.apache.james.mailbox.cassandra.CassandraMailboxManager; import org.apache.james.mailbox.cassandra.CassandraMailboxSessionMapperFactory; import org.apache.james.mailbox.cassandra.CassandraMessageId; +import org.apache.james.mailbox.cassandra.mail.CassandraMailboxCounterDAO; +import org.apache.james.mailbox.cassandra.mail.CassandraMailboxRecentsDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO; @@ -39,6 +41,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule; import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule; import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule; +import org.apache.james.mailbox.cassandra.modules.CassandraMailboxRecentsModule; import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule; import org.apache.james.mailbox.cassandra.modules.CassandraModSeqModule; import org.apache.james.mailbox.cassandra.modules.CassandraQuotaModule; @@ -78,6 +81,7 @@ public class CassandraHostSystem extends JamesImapHostSystem { new CassandraMailboxModule(), new CassandraMessageModule(), new CassandraMailboxCounterModule(), + new CassandraMailboxRecentsModule(), new CassandraUidModule(), new CassandraModSeqModule(), new CassandraSubscriptionModule(), @@ -94,9 +98,11 @@ public class CassandraHostSystem extends JamesImapHostSystem { CassandraMessageDAO messageDAO = new CassandraMessageDAO(session, typesProvider, messageIdFactory); CassandraMessageIdDAO messageIdDAO = new CassandraMessageIdDAO(session, messageIdFactory); CassandraMessageIdToImapUidDAO imapUidDAO = new CassandraMessageIdToImapUidDAO(session, messageIdFactory); + CassandraMailboxCounterDAO mailboxCounterDAO = new CassandraMailboxCounterDAO(session); + CassandraMailboxRecentsDAO mailboxRecentsDAO = new CassandraMailboxRecentsDAO(session); CassandraMailboxSessionMapperFactory mapperFactory = new CassandraMailboxSessionMapperFactory(uidProvider, modSeqProvider, - session, typesProvider, messageDAO, messageIdDAO, imapUidDAO); + session, typesProvider, messageDAO, messageIdDAO, imapUidDAO, mailboxCounterDAO, mailboxRecentsDAO); mailboxManager = new CassandraMailboxManager(mapperFactory, userManager, new JVMMailboxPathLocker(), new MessageParser(), messageIdFactory); QuotaRootResolver quotaRootResolver = new DefaultQuotaRootResolver(mapperFactory); http://git-wip-us.apache.org/repos/asf/james-project/blob/c8c12826/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java ---------------------------------------------------------------------- diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java index 7ad3a28..df0693f 100644 --- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java +++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java @@ -98,6 +98,7 @@ public class CassandraMailboxModule extends AbstractModule { Multibinder<CassandraModule> cassandraDataDefinitions = Multibinder.newSetBinder(binder(), CassandraModule.class); cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraAclModule.class); cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule.class); + cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraMailboxRecentsModule.class); cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule.class); cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraMessageModule.class); cassandraDataDefinitions.addBinding().to(org.apache.james.mailbox.cassandra.modules.CassandraSubscriptionModule.class); --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org