This is an automated email from the ASF dual-hosted git repository. rcordier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 4f5d8c43f4ae83a1847476dea698428b8d8788fd Author: Benoit Tellier <[email protected]> AuthorDate: Thu May 13 15:39:52 2021 +0700 [REFACTORING] Reactive StoreMessageIdManager::validateQuota This ensures using StoreMessageIdManager::setInMailboxesReactive do not block for the purpose of quota validation for copy use cases. --- .../james/mailbox/store/StoreMessageIdManager.java | 60 +++++++++++++--------- .../AbstractMessageIdManagerSideEffectTest.java | 22 ++++---- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java index a7fa33b..b1ac262 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java @@ -46,6 +46,7 @@ import org.apache.james.mailbox.RightManager; import org.apache.james.mailbox.events.MailboxIdRegistrationKey; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.MailboxNotFoundException; +import org.apache.james.mailbox.exception.OverQuotaException; import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData; import org.apache.james.mailbox.model.DeleteResult; @@ -357,7 +358,7 @@ public class StoreMessageIdManager implements MessageIdManager { .map(mailbox -> Pair.of(message, mailbox))) .collect(Guavate.toImmutableList()); - return Mono.fromRunnable(Throwing.runnable(() -> validateQuota(messageMoves, mailboxMessage.get())).sneakyThrow()) + return validateQuota(messageMoves, mailboxMessage.get()) .then(Mono.fromRunnable(Throwing.runnable(() -> addMessageToMailboxes(mailboxMessage.get(), messageMoves.addedMailboxes(), mailboxSession)).sneakyThrow())) .then(removeMessageFromMailboxes(mailboxMessage.get().getMessageId(), messagesToRemove, mailboxSession)) @@ -415,33 +416,44 @@ public class StoreMessageIdManager implements MessageIdManager { return Mono.empty(); } - private void validateQuota(MessageMovesWithMailbox messageMoves, MailboxMessage mailboxMessage) throws MailboxException { + private Mono<Void> validateQuota(MessageMovesWithMailbox messageMoves, MailboxMessage mailboxMessage) { Map<QuotaRoot, Integer> messageCountByQuotaRoot = buildMapQuotaRoot(messageMoves); - for (Map.Entry<QuotaRoot, Integer> entry : messageCountByQuotaRoot.entrySet()) { - Integer additionalCopyCount = entry.getValue(); - if (additionalCopyCount > 0) { - long additionalOccupiedSpace = additionalCopyCount * mailboxMessage.getFullContentOctets(); - new QuotaChecker(quotaManager.getQuotas(entry.getKey()), entry.getKey()) - .tryAddition(additionalCopyCount, additionalOccupiedSpace); - } - } + + return Flux.fromIterable(messageCountByQuotaRoot.entrySet()) + .filter(entry -> entry.getValue() > 0) + .flatMap(entry -> Mono.from(quotaManager.getQuotasReactive(entry.getKey())) + .map(quotas -> new QuotaChecker(quotas, entry.getKey())) + .handle((quotaChecker, sink) -> { + Integer additionalCopyCount = entry.getValue(); + long additionalOccupiedSpace = additionalCopyCount * mailboxMessage.getFullContentOctets(); + try { + quotaChecker.tryAddition(additionalCopyCount, additionalOccupiedSpace); + } catch (OverQuotaException e) { + sink.error(e); + } + })) + .then(); } - private Map<QuotaRoot, Integer> buildMapQuotaRoot(MessageMovesWithMailbox messageMoves) throws MailboxException { - Map<QuotaRoot, Integer> messageCountByQuotaRoot = new HashMap<>(); - for (Mailbox mailbox : messageMoves.addedMailboxes()) { - QuotaRoot quotaRoot = quotaRootResolver.getQuotaRoot(mailbox); - int currentCount = Optional.ofNullable(messageCountByQuotaRoot.get(quotaRoot)) - .orElse(0); - messageCountByQuotaRoot.put(quotaRoot, currentCount + 1); - } - for (Mailbox mailbox : messageMoves.removedMailboxes()) { - QuotaRoot quotaRoot = quotaRootResolver.getQuotaRoot(mailbox); - int currentCount = Optional.ofNullable(messageCountByQuotaRoot.get(quotaRoot)) - .orElse(0); - messageCountByQuotaRoot.put(quotaRoot, currentCount - 1); + private Map<QuotaRoot, Integer> buildMapQuotaRoot(MessageMovesWithMailbox messageMoves) { + try { + Map<QuotaRoot, Integer> messageCountByQuotaRoot = new HashMap<>(); + for (Mailbox mailbox : messageMoves.addedMailboxes()) { + QuotaRoot quotaRoot = quotaRootResolver.getQuotaRoot(mailbox); + int currentCount = Optional.ofNullable(messageCountByQuotaRoot.get(quotaRoot)) + .orElse(0); + messageCountByQuotaRoot.put(quotaRoot, currentCount + 1); + } + for (Mailbox mailbox : messageMoves.removedMailboxes()) { + QuotaRoot quotaRoot = quotaRootResolver.getQuotaRoot(mailbox); + int currentCount = Optional.ofNullable(messageCountByQuotaRoot.get(quotaRoot)) + .orElse(0); + messageCountByQuotaRoot.put(quotaRoot, currentCount - 1); + } + return messageCountByQuotaRoot; + } catch (MailboxException e) { + throw new RuntimeException(e); } - return messageCountByQuotaRoot; } private void addMessageToMailboxes(MailboxMessage mailboxMessage, Set<Mailbox> mailboxes, MailboxSession mailboxSession) throws MailboxException { diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java index a6011de..1c86c65 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java @@ -56,7 +56,6 @@ import org.apache.james.mailbox.events.MailboxEvents.Expunged; import org.apache.james.mailbox.events.MailboxEvents.FlagsUpdated; import org.apache.james.mailbox.events.MailboxEvents.MailboxEvent; import org.apache.james.mailbox.events.MessageMoveEvent; -import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.OverQuotaException; import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.fixture.MailboxFixture; @@ -115,6 +114,11 @@ public abstract class AbstractMessageIdManagerSideEffectTest { eventCollector = new EventCollector(); quotaManager = mock(QuotaManager.class); + when(quotaManager.getQuotasReactive(any(QuotaRoot.class))) + .thenReturn(Mono.just(new QuotaManager.Quotas( + Quota.<QuotaCountLimit, QuotaCountUsage>builder().used(QuotaCountUsage.count(102)).computedLimit(QuotaCountLimit.unlimited()).build(), + Quota.<QuotaSizeLimit, QuotaSizeUsage>builder().used(QuotaSizeUsage.size(2)).computedLimit(QuotaSizeLimit.unlimited()).build()))); + session = MailboxSessionUtil.create(ALICE); setupMockForPreDeletionHooks(); testingData = createTestSystem(quotaManager, eventBus, ImmutableSet.of(preDeletionHook1, preDeletionHook2)); @@ -382,13 +386,13 @@ public abstract class AbstractMessageIdManagerSideEffectTest { } @Test - void setInMailboxesShouldThrowExceptionWhenOverQuota() throws Exception { + void setInMailboxesShouldThrowExceptionWhenOverQuota() { MessageId messageId = testingData.persist(mailbox1.getMailboxId(), messageUid1, FLAGS, session); - when(quotaManager.getQuotas(any(QuotaRoot.class))) - .thenReturn(new QuotaManager.Quotas( + when(quotaManager.getQuotasReactive(any(QuotaRoot.class))) + .thenReturn(Mono.just(new QuotaManager.Quotas( OVER_QUOTA, - Quota.<QuotaSizeLimit, QuotaSizeUsage>builder().used(QuotaSizeUsage.size(2)).computedLimit(QuotaSizeLimit.unlimited()).build())); + Quota.<QuotaSizeLimit, QuotaSizeUsage>builder().used(QuotaSizeUsage.size(2)).computedLimit(QuotaSizeLimit.unlimited()).build()))); assertThatThrownBy(() -> messageIdManager.setInMailboxes(messageId, ImmutableList.of(mailbox1.getMailboxId(), mailbox2.getMailboxId()), @@ -553,10 +557,10 @@ public abstract class AbstractMessageIdManagerSideEffectTest { assertThat(eventCollector.getEvents()).isEmpty(); } - protected void givenUnlimitedQuota() throws MailboxException { - when(quotaManager.getQuotas(any(QuotaRoot.class))) - .thenReturn(new QuotaManager.Quotas( + protected void givenUnlimitedQuota() { + when(quotaManager.getQuotasReactive(any(QuotaRoot.class))) + .thenReturn(Mono.just(new QuotaManager.Quotas( Quota.<QuotaCountLimit, QuotaCountUsage>builder().used(QuotaCountUsage.count(2)).computedLimit(QuotaCountLimit.unlimited()).build(), - Quota.<QuotaSizeLimit, QuotaSizeUsage>builder().used(QuotaSizeUsage.size(2)).computedLimit(QuotaSizeLimit.unlimited()).build())); + Quota.<QuotaSizeLimit, QuotaSizeUsage>builder().used(QuotaSizeUsage.size(2)).computedLimit(QuotaSizeLimit.unlimited()).build()))); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
