You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2021/05/14 06:42:36 UTC
[james-project] 04/15: [REFACTORING] Fasten Mailbox/get &
Email/query with reactive MailboxManager::getMailbox
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 2bc8a96582ef1447dd630fafc4fa6b09007c7e82
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri May 7 18:12:28 2021 +0700
[REFACTORING] Fasten Mailbox/get & Email/query with reactive MailboxManager::getMailbox
---
.../org/apache/james/mailbox/MailboxManager.java | 4 +
.../quota/InMemoryCurrentQuotaManager.java | 14 +--
.../james/mailbox/store/StoreMailboxManager.java | 54 +++++---
.../jmap/draft/methods/GetMailboxesMethod.java | 18 +--
.../jmap/draft/methods/GetMessageListMethod.java | 9 +-
.../methods/SetMailboxesCreationProcessor.java | 3 +-
.../methods/SetMailboxesDestructionProcessor.java | 3 +-
.../draft/methods/SetMailboxesUpdateProcessor.java | 1 +
.../james/jmap/draft/model/MailboxFactory.java | 138 +++++++++++----------
.../methods/SetMailboxesUpdateProcessorTest.java | 4 +-
.../james/jmap/draft/model/MailboxFactoryTest.java | 31 ++---
.../james/jmap/method/EmailQueryMethod.scala | 6 +-
.../data/jmap/EmailQueryViewPopulator.java | 3 +-
.../jmap/MessageFastViewProjectionCorrector.java | 3 +-
14 files changed, 154 insertions(+), 137 deletions(-)
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java b/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java
index a175127..6ee804b 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java
@@ -139,6 +139,10 @@ public interface MailboxManager extends RequestAware, RightManager, MailboxAnnot
*/
MessageManager getMailbox(MailboxId mailboxId, MailboxSession session) throws MailboxException;
+ Publisher<MessageManager> getMailboxReactive(MailboxId mailboxId, MailboxSession session);
+
+ Publisher<MessageManager> getMailboxReactive(MailboxPath mailboxPath, MailboxSession session);
+
/**
* Creates a new mailbox. Any intermediary mailboxes missing from the
* hierarchy should be created.
diff --git a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManager.java b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManager.java
index 120df80..26b35dc 100644
--- a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManager.java
+++ b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManager.java
@@ -60,7 +60,6 @@ public class InMemoryCurrentQuotaManager implements CurrentQuotaManager {
public CurrentQuotas loadQuotas(QuotaRoot quotaRoot, CurrentQuotaCalculator quotaCalculator, SessionProvider sessionProvider) {
return quotaCalculator.recalculateCurrentQuotas(quotaRoot, sessionProvider.createSystemSession(Username.of(quotaRoot.getValue())))
- .subscribeOn(Schedulers.elastic())
.block();
}
@@ -77,22 +76,20 @@ public class InMemoryCurrentQuotaManager implements CurrentQuotaManager {
@Override
public Mono<QuotaCountUsage> getCurrentMessageCount(QuotaRoot quotaRoot) {
return Mono.fromCallable(() -> quotaCache.get(quotaRoot).get().count())
- .onErrorMap(this::wrapAsMailboxException)
- .subscribeOn(Schedulers.elastic());
+ .onErrorMap(this::wrapAsMailboxException);
}
@Override
public Mono<QuotaSizeUsage> getCurrentStorage(QuotaRoot quotaRoot) {
return Mono.fromCallable(() -> quotaCache.get(quotaRoot).get().size())
- .onErrorMap(this::wrapAsMailboxException)
- .subscribeOn(Schedulers.elastic());
+ .onErrorMap(this::wrapAsMailboxException);
}
@Override
public Mono<CurrentQuotas> getCurrentQuotas(QuotaRoot quotaRoot) {
return Mono.fromCallable(() -> quotaCache.get(quotaRoot).get())
- .onErrorMap(this::wrapAsMailboxException)
- .subscribeOn(Schedulers.elastic());
+ .subscribeOn(Schedulers.elastic())
+ .onErrorMap(this::wrapAsMailboxException);
}
@Override
@@ -100,8 +97,7 @@ public class InMemoryCurrentQuotaManager implements CurrentQuotaManager {
return getCurrentQuotas(quotaOperation.quotaRoot())
.filter(Predicate.not(Predicate.isEqual(CurrentQuotas.from(quotaOperation))))
.flatMap(storedQuotas -> decrease(new QuotaOperation(quotaOperation.quotaRoot(), storedQuotas.count(), storedQuotas.size()))
- .then(increase(quotaOperation)))
- .subscribeOn(Schedulers.elastic());
+ .then(increase(quotaOperation)));
}
private Mono<Void> updateQuota(QuotaRoot quotaRoot, UnaryOperator<CurrentQuotas> quotaFunction) {
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
index ceabd4d..6837272 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
@@ -87,6 +87,7 @@ import org.apache.james.mailbox.store.search.MessageSearchIndex;
import org.apache.james.mailbox.store.user.SubscriptionMapper;
import org.apache.james.mailbox.store.user.model.Subscription;
import org.apache.james.util.FunctionalUtils;
+import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -265,37 +266,50 @@ public class StoreMailboxManager implements MailboxManager {
@Override
public MessageManager getMailbox(MailboxPath mailboxPath, MailboxSession session) throws MailboxException {
- final MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session);
- Mailbox mailboxRow = mapper.findMailboxByPath(mailboxPath)
- .blockOptional()
- .orElseThrow(() -> {
- LOGGER.info("Mailbox '{}' not found.", mailboxPath);
- return new MailboxNotFoundException(mailboxPath);
- });
+ return MailboxReactorUtils.block(getMailboxReactive(mailboxPath, session));
+ }
- if (!assertUserHasAccessTo(mailboxRow, session)) {
- LOGGER.info("Mailbox '{}' does not belong to user '{}' but to '{}'", mailboxPath, session.getUser(), mailboxRow.getUser());
- throw new MailboxNotFoundException(mailboxPath);
- }
+ @Override
+ public Mono<MessageManager> getMailboxReactive(MailboxPath mailboxPath, MailboxSession session) {
+ MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session);
+
+ return mapper.findMailboxByPath(mailboxPath)
+ .map(Throwing.<Mailbox, MessageManager>function(mailboxRow -> {
+ if (!assertUserHasAccessTo(mailboxRow, session)) {
+ LOGGER.info("Mailbox '{}' does not belong to user '{}' but to '{}'", mailboxPath, session.getUser(), mailboxRow.getUser());
+ throw new MailboxNotFoundException(mailboxPath);
+ }
- LOGGER.debug("Loaded mailbox {}", mailboxPath);
+ LOGGER.debug("Loaded mailbox {}", mailboxPath);
- return createMessageManager(mailboxRow, session);
+ return createMessageManager(mailboxRow, session);
+ }).sneakyThrow())
+ .switchIfEmpty(Mono.fromCallable(() -> {
+ LOGGER.info("Mailbox '{}' not found.", mailboxPath);
+ throw new MailboxNotFoundException(mailboxPath);
+ }));
}
@Override
public MessageManager getMailbox(MailboxId mailboxId, MailboxSession session) throws MailboxException {
+ return block(getMailboxReactive(mailboxId, session));
+ }
+
+ @Override
+ public Publisher<MessageManager> getMailboxReactive(MailboxId mailboxId, MailboxSession session) {
MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session);
- Mailbox mailboxRow = block(mapper.findMailboxById(mailboxId));
- if (!assertUserHasAccessTo(mailboxRow, session)) {
- LOGGER.info("Mailbox '{}' does not belong to user '{}' but to '{}'", mailboxId.serialize(), session.getUser(), mailboxRow.getUser());
- throw new MailboxNotFoundException(mailboxId);
- }
+ return mapper.findMailboxById(mailboxId)
+ .map(Throwing.<Mailbox, MessageManager>function(mailboxRow -> {
+ if (!assertUserHasAccessTo(mailboxRow, session)) {
+ LOGGER.info("Mailbox '{} {}' does not belong to user '{}' but to '{}'", mailboxRow.getMailboxId().serialize(), mailboxRow.generateAssociatedPath(), session.getUser(), mailboxRow.getUser());
+ throw new MailboxNotFoundException(mailboxId);
+ }
- LOGGER.debug("Loaded mailbox {}", mailboxId.serialize());
+ LOGGER.debug("Loaded mailbox {} {}", mailboxRow.getMailboxId().serialize(), mailboxRow.generateAssociatedPath());
- return createMessageManager(mailboxRow, session);
+ return createMessageManager(mailboxRow, session);
+ }).sneakyThrow());
}
private boolean assertUserHasAccessTo(Mailbox mailbox, MailboxSession session) {
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMailboxesMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMailboxesMethod.java
index 610924f..8381fdc 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMailboxesMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMailboxesMethod.java
@@ -21,7 +21,6 @@ package org.apache.james.jmap.draft.methods;
import static org.apache.james.util.ReactorUtils.DEFAULT_CONCURRENCY;
import static org.apache.james.util.ReactorUtils.context;
-import static org.apache.james.util.ReactorUtils.publishIfPresent;
import java.util.Comparator;
import java.util.List;
@@ -57,7 +56,6 @@ import com.google.common.collect.Sets;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
-import reactor.core.scheduler.Schedulers;
public class GetMailboxesMethod implements Method {
@@ -143,32 +141,26 @@ public class GetMailboxesMethod implements Method {
private Flux<Mailbox> retrieveSpecificMailboxes(MailboxSession mailboxSession, ImmutableList<MailboxId> mailboxIds) {
return Flux.fromIterable(mailboxIds)
- .flatMap(mailboxId -> Mono.fromCallable(() ->
- mailboxFactory.builder()
+ .flatMap(mailboxId -> mailboxFactory.builder()
.id(mailboxId)
.session(mailboxSession)
.usingPreloadedMailboxesMetadata(NO_PRELOADED_METADATA)
- .build())
- .subscribeOn(Schedulers.elastic()), DEFAULT_CONCURRENCY)
- .handle(publishIfPresent());
+ .build(), DEFAULT_CONCURRENCY);
}
private Flux<Mailbox> retrieveAllMailboxes(MailboxSession mailboxSession) {
Mono<List<MailboxMetaData>> userMailboxesMono = getAllMailboxesMetaData(mailboxSession).collectList();
- Mono<QuotaLoaderWithDefaultPreloaded> quotaLoaderMono = Mono.fromCallable(() ->
- new QuotaLoaderWithDefaultPreloaded(quotaRootResolver, quotaManager, mailboxSession))
- .subscribeOn(Schedulers.elastic());
+ Mono<QuotaLoaderWithDefaultPreloaded> quotaLoaderMono = QuotaLoaderWithDefaultPreloaded.preLoad(quotaRootResolver, quotaManager, mailboxSession);
return userMailboxesMono.zipWith(quotaLoaderMono)
.flatMapMany(
tuple -> Flux.fromIterable(tuple.getT1())
- .map(mailboxMetaData -> mailboxFactory.builder()
+ .flatMap(mailboxMetaData -> mailboxFactory.builder()
.mailboxMetadata(mailboxMetaData)
.session(mailboxSession)
.usingPreloadedMailboxesMetadata(Optional.of(tuple.getT1()))
.quotaLoader(tuple.getT2())
- .build())
- .handle(publishIfPresent()));
+ .build()));
}
private Flux<MailboxMetaData> getAllMailboxesMetaData(MailboxSession mailboxSession) {
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessageListMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessageListMethod.java
index 69d64d5e..caad396 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessageListMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessageListMethod.java
@@ -115,8 +115,7 @@ public class GetMessageListMethod implements Method {
return metricFactory.decorateSupplierWithTimerMetricLogP99(JMAP_PREFIX + METHOD_NAME.getName(),
() -> process(methodCallId, mailboxSession, messageListRequest)
- .subscriberContext(context("GET_MESSAGE_LIST", mdc(messageListRequest))))
- .subscribeOn(Schedulers.elastic());
+ .subscriberContext(context("GET_MESSAGE_LIST", mdc(messageListRequest))));
}
private MDCBuilder mdc(GetMessageListRequest messageListRequest) {
@@ -171,8 +170,7 @@ public class GetMessageListMethod implements Method {
MailboxId mailboxId = mailboxIdFactory.fromString(mailboxIdAsString);
Limit aLimit = Limit.from(Math.toIntExact(limit));
- return Mono.fromCallable(() -> mailboxManager.getMailbox(mailboxId, mailboxSession))
- .subscribeOn(Schedulers.elastic())
+ return Mono.from(mailboxManager.getMailboxReactive(mailboxId, mailboxSession))
.then(emailQueryView.listMailboxContent(mailboxId, aLimit)
.skip(position)
.take(limit)
@@ -188,8 +186,7 @@ public class GetMessageListMethod implements Method {
ZonedDateTime after = condition.getAfter().get();
Limit aLimit = Limit.from(Math.toIntExact(limit));
- return Mono.fromCallable(() -> mailboxManager.getMailbox(mailboxId, mailboxSession))
- .subscribeOn(Schedulers.elastic())
+ return Mono.from(mailboxManager.getMailboxReactive(mailboxId, mailboxSession))
.then(emailQueryView.listMailboxContentSinceReceivedAt(mailboxId, after, aLimit)
.skip(position)
.take(limit)
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesCreationProcessor.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesCreationProcessor.java
index c75b462..25a1a69 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesCreationProcessor.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesCreationProcessor.java
@@ -121,7 +121,8 @@ public class SetMailboxesCreationProcessor implements SetMailboxesProcessor {
Optional<Mailbox> mailbox = mailboxId.flatMap(id -> mailboxFactory.builder()
.id(id)
.session(mailboxSession)
- .build());
+ .build()
+ .blockOptional());
if (mailbox.isPresent()) {
subscriptionManager.subscribe(mailboxSession, mailboxPath.getName());
builder.created(mailboxCreationId, mailbox.get());
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesDestructionProcessor.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesDestructionProcessor.java
index 1238147..dbd2e1e 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesDestructionProcessor.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesDestructionProcessor.java
@@ -98,7 +98,8 @@ public class SetMailboxesDestructionProcessor implements SetMailboxesProcessor {
.map(id -> mailboxFactory.builder()
.id(id)
.session(mailboxSession)
- .build())
+ .build()
+ .blockOptional())
.flatMap(Optional::stream)
.forEach(mailbox -> idToMailboxBuilder.put(mailbox.getId(), mailbox));
return idToMailboxBuilder.build();
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessor.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessor.java
index acf2747..33aa98e 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessor.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessor.java
@@ -181,6 +181,7 @@ public class SetMailboxesUpdateProcessor implements SetMailboxesProcessor {
.id(mailboxId)
.session(mailboxSession)
.build()
+ .blockOptional()
.orElseThrow(() -> new MailboxNotFoundException(mailboxId));
}
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MailboxFactory.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MailboxFactory.java
index d4597b7..7f3f723 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MailboxFactory.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MailboxFactory.java
@@ -26,7 +26,6 @@ import javax.inject.Inject;
import org.apache.james.core.Username;
import org.apache.james.jmap.draft.model.mailbox.Mailbox;
import org.apache.james.jmap.draft.model.mailbox.MailboxNamespace;
-import org.apache.james.jmap.draft.model.mailbox.Quotas;
import org.apache.james.jmap.draft.model.mailbox.Rights;
import org.apache.james.jmap.draft.model.mailbox.SortOrder;
import org.apache.james.jmap.draft.utils.quotas.DefaultQuotaLoader;
@@ -35,7 +34,6 @@ import org.apache.james.mailbox.MailboxManager;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.MessageManager;
import org.apache.james.mailbox.Role;
-import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.exception.MailboxNotFoundException;
import org.apache.james.mailbox.model.MailboxACL;
import org.apache.james.mailbox.model.MailboxCounters;
@@ -52,8 +50,31 @@ import com.google.common.base.Splitter;
import com.google.common.primitives.Booleans;
import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
public class MailboxFactory {
+ private static class MailboxTuple {
+ public static MailboxTuple from(MailboxMetaData metaData) {
+ return new MailboxTuple(metaData.getPath(), metaData.getCounters().sanitize(), metaData.getResolvedAcls());
+ }
+
+ public static Mono<MailboxTuple> from(MessageManager messageManager, MailboxSession session) {
+ return Mono.fromCallable(() ->
+ new MailboxTuple(messageManager.getMailboxPath(), messageManager.getMailboxCounters(session).sanitize(), messageManager.getResolvedAcl(session)))
+ .subscribeOn(Schedulers.elastic());
+ }
+
+ private final MailboxPath mailboxPath;
+ private final MailboxCounters.Sanitized mailboxCounters;
+ private final MailboxACL acl;
+
+ private MailboxTuple(MailboxPath mailboxPath, MailboxCounters.Sanitized mailboxCounters, MailboxACL acl) {
+ this.mailboxPath = mailboxPath;
+ this.mailboxCounters = mailboxCounters;
+ this.acl = acl;
+ }
+ }
+
private final MailboxManager mailboxManager;
private final QuotaManager quotaManager;
private final QuotaRootResolver quotaRootResolver;
@@ -96,36 +117,25 @@ public class MailboxFactory {
return this;
}
- public Optional<Mailbox> build() {
+ public Mono<Mailbox> build() {
Preconditions.checkNotNull(session);
- try {
- MailboxId mailboxId = computeMailboxId();
- Mono<MessageManager> mailbox = mailbox(mailboxId).cache();
-
- MailboxACL mailboxACL = mailboxMetaData.map(MailboxMetaData::getResolvedAcls)
- .orElseGet(Throwing.supplier(() -> retrieveCachedMailbox(mailboxId, mailbox).getResolvedAcl(session)).sneakyThrow());
-
- MailboxPath mailboxPath = mailboxMetaData.map(MailboxMetaData::getPath)
- .orElseGet(Throwing.supplier(() -> retrieveCachedMailbox(mailboxId, mailbox).getMailboxPath()).sneakyThrow());
-
- MailboxCounters.Sanitized mailboxCounters = mailboxMetaData.map(MailboxMetaData::getCounters)
- .orElseGet(Throwing.supplier(() -> retrieveCachedMailbox(mailboxId, mailbox).getMailboxCounters(session)).sneakyThrow())
- .sanitize();
-
- return Optional.of(mailboxFactory.from(
- mailboxId,
- mailboxPath,
- mailboxCounters,
- mailboxACL,
- userMailboxesMetadata,
- quotaLoader,
- session));
- } catch (MailboxNotFoundException e) {
- return Optional.empty();
- } catch (MailboxException e) {
- throw new RuntimeException(e);
- }
+ MailboxId mailboxId = computeMailboxId();
+
+ Mono<MailboxTuple> mailbox = mailboxMetaData.map(MailboxTuple::from)
+ .map(Mono::just)
+ .orElse(Mono.from(mailboxFactory.mailboxManager.getMailboxReactive(mailboxId, session))
+ .flatMap(messageManager -> MailboxTuple.from(messageManager, session)));
+
+ return mailbox.flatMap(tuple -> mailboxFactory.from(
+ mailboxId,
+ tuple.mailboxPath,
+ tuple.mailboxCounters,
+ tuple.acl,
+ userMailboxesMetadata,
+ quotaLoader,
+ session))
+ .onErrorResume(MailboxNotFoundException.class, e -> Mono.empty());
}
private MailboxId computeMailboxId() {
@@ -137,14 +147,13 @@ public class MailboxFactory {
}
private Mono<MessageManager> mailbox(MailboxId mailboxId) {
- return Mono.fromCallable(() -> mailboxFactory.mailboxManager.getMailbox(mailboxId, session));
+ return Mono.from(mailboxFactory.mailboxManager.getMailboxReactive(mailboxId, session));
}
- private MessageManager retrieveCachedMailbox(MailboxId mailboxId, Mono<MessageManager> mailbox) throws MailboxNotFoundException {
+ private Mono<MessageManager> retrieveCachedMailbox(MailboxId mailboxId, Mono<MessageManager> mailbox) throws MailboxNotFoundException {
return mailbox
.onErrorResume(MailboxNotFoundException.class, any -> Mono.empty())
- .blockOptional()
- .orElseThrow(() -> new MailboxNotFoundException(mailboxId));
+ .switchIfEmpty(Mono.error(() -> new MailboxNotFoundException(mailboxId)));
}
}
@@ -160,13 +169,13 @@ public class MailboxFactory {
return new MailboxBuilder(this, defaultQuotaLoader);
}
- private Mailbox from(MailboxId mailboxId,
+ private Mono<Mailbox> from(MailboxId mailboxId,
MailboxPath mailboxPath,
MailboxCounters.Sanitized mailboxCounters,
MailboxACL resolvedAcl,
Optional<List<MailboxMetaData>> userMailboxesMetadata,
QuotaLoader quotaLoader,
- MailboxSession mailboxSession) throws MailboxException {
+ MailboxSession mailboxSession) {
boolean isOwner = mailboxPath.belongsTo(mailboxSession);
Optional<Role> role = Role.from(mailboxPath.getName())
.filter(any -> mailboxPath.belongsTo(mailboxSession));
@@ -175,26 +184,27 @@ public class MailboxFactory {
.removeEntriesFor(mailboxPath.getUser());
Username username = mailboxSession.getUser();
- Quotas quotas = quotaLoader.getQuotas(mailboxPath);
-
- return Mailbox.builder()
- .id(mailboxId)
- .name(getName(mailboxPath, mailboxSession))
- .parentId(getParentIdFromMailboxPath(mailboxPath, userMailboxesMetadata, mailboxSession).orElse(null))
- .role(role)
- .unreadMessages(mailboxCounters.getUnseen())
- .totalMessages(mailboxCounters.getCount())
- .sortOrder(SortOrder.getSortOrder(role))
- .sharedWith(rights)
- .mayAddItems(rights.mayAddItems(username).orElse(isOwner))
- .mayCreateChild(rights.mayCreateChild(username).orElse(isOwner))
- .mayDelete(rights.mayDelete(username).orElse(isOwner))
- .mayReadItems(rights.mayReadItems(username).orElse(isOwner))
- .mayRemoveItems(rights.mayRemoveItems(username).orElse(isOwner))
- .mayRename(rights.mayRename(username).orElse(isOwner))
- .namespace(getNamespace(mailboxPath, isOwner))
- .quotas(quotas)
- .build();
+ return Mono.zip(
+ quotaLoader.getQuotas(mailboxPath),
+ getParentIdFromMailboxPath(mailboxPath, userMailboxesMetadata, mailboxSession))
+ .map(tuple -> Mailbox.builder()
+ .id(mailboxId)
+ .name(getName(mailboxPath, mailboxSession))
+ .parentId(tuple.getT2().orElse(null))
+ .role(role)
+ .unreadMessages(mailboxCounters.getUnseen())
+ .totalMessages(mailboxCounters.getCount())
+ .sortOrder(SortOrder.getSortOrder(role))
+ .sharedWith(rights)
+ .mayAddItems(rights.mayAddItems(username).orElse(isOwner))
+ .mayCreateChild(rights.mayCreateChild(username).orElse(isOwner))
+ .mayDelete(rights.mayDelete(username).orElse(isOwner))
+ .mayReadItems(rights.mayReadItems(username).orElse(isOwner))
+ .mayRemoveItems(rights.mayRemoveItems(username).orElse(isOwner))
+ .mayRename(rights.mayRename(username).orElse(isOwner))
+ .namespace(getNamespace(mailboxPath, isOwner))
+ .quotas(tuple.getT1())
+ .build());
}
private MailboxNamespace getNamespace(MailboxPath mailboxPath, boolean isOwner) {
@@ -215,21 +225,21 @@ public class MailboxFactory {
}
@VisibleForTesting
- Optional<MailboxId> getParentIdFromMailboxPath(MailboxPath mailboxPath, Optional<List<MailboxMetaData>> userMailboxesMetadata,
- MailboxSession mailboxSession) throws MailboxException {
+ Mono<Optional<MailboxId>> getParentIdFromMailboxPath(MailboxPath mailboxPath, Optional<List<MailboxMetaData>> userMailboxesMetadata,
+ MailboxSession mailboxSession) {
List<MailboxPath> levels = mailboxPath.getHierarchyLevels(mailboxSession.getPathDelimiter());
if (levels.size() <= 1) {
- return Optional.empty();
+ return Mono.just(Optional.empty());
}
MailboxPath parent = levels.get(levels.size() - 2);
- return userMailboxesMetadata.map(list -> retrieveParentFromMetadata(parent, list))
+ return userMailboxesMetadata.map(list -> Mono.just(retrieveParentFromMetadata(parent, list)))
.orElseGet(Throwing.supplier(() -> retrieveParentFromBackend(mailboxSession, parent)).sneakyThrow());
}
- private Optional<MailboxId> retrieveParentFromBackend(MailboxSession mailboxSession, MailboxPath parent) throws MailboxException {
- return Optional.of(
- mailboxManager.getMailbox(parent, mailboxSession)
- .getId());
+ private Mono<Optional<MailboxId>> retrieveParentFromBackend(MailboxSession mailboxSession, MailboxPath parent) {
+ return Mono.from(mailboxManager.getMailboxReactive(parent, mailboxSession))
+ .map(MessageManager::getId)
+ .map(Optional::of);
}
private Optional<MailboxId> retrieveParentFromMetadata(MailboxPath parent, List<MailboxMetaData> list) {
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java
index 79859c4..7faa903 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java
@@ -45,6 +45,8 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import reactor.core.publisher.Mono;
+
public class SetMailboxesUpdateProcessorTest {
private MailboxManager mockedMailboxManager;
@@ -79,7 +81,7 @@ public class SetMailboxesUpdateProcessorTest {
when(mockBuilder.session(mockedMailboxSession))
.thenReturn(mockBuilder);
when(mockBuilder.build())
- .thenReturn(Optional.of(mailbox));
+ .thenReturn(Mono.just(mailbox));
when(mockedMailboxFactory.builder())
.thenReturn(mockBuilder);
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MailboxFactoryTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MailboxFactoryTest.java
index 22e6c8f..e2ee241 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MailboxFactoryTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MailboxFactoryTest.java
@@ -82,7 +82,8 @@ public class MailboxFactoryTest {
Optional<Mailbox> mailbox = sut.builder()
.id(InMemoryId.of(123))
.session(mailboxSession)
- .build();
+ .build()
+ .blockOptional();
assertThat(mailbox).isEmpty();
}
@@ -96,7 +97,8 @@ public class MailboxFactoryTest {
Optional<Mailbox> mailbox = sut.builder()
.id(mailboxId)
.session(mailboxSession)
- .build();
+ .build()
+ .blockOptional();
assertThat(mailbox).isPresent();
assertThat(mailbox.get().getId()).isEqualTo(mailboxId);
@@ -134,7 +136,7 @@ public class MailboxFactoryTest {
MailboxPath mailboxPath = MailboxPath.forUser(user, "mailbox");
mailboxManager.createMailbox(mailboxPath, mailboxSession);
- Optional<MailboxId> id = sut.getParentIdFromMailboxPath(mailboxPath, Optional.empty(), mailboxSession);
+ Optional<MailboxId> id = sut.getParentIdFromMailboxPath(mailboxPath, Optional.empty(), mailboxSession).block();
assertThat(id).isEmpty();
}
@@ -147,7 +149,7 @@ public class MailboxFactoryTest {
MailboxPath mailboxPath = parentMailboxPath.child("mailbox", '.');
mailboxManager.createMailbox(mailboxPath, mailboxSession);
- Optional<MailboxId> id = sut.getParentIdFromMailboxPath(mailboxPath, Optional.empty(), mailboxSession);
+ Optional<MailboxId> id = sut.getParentIdFromMailboxPath(mailboxPath, Optional.empty(), mailboxSession).block();
assertThat(id).contains(parentId);
}
@@ -162,7 +164,7 @@ public class MailboxFactoryTest {
mailboxManager.createMailbox(mailboxPath, mailboxSession);
- Optional<MailboxId> id = sut.getParentIdFromMailboxPath(mailboxPath, Optional.empty(), mailboxSession);
+ Optional<MailboxId> id = sut.getParentIdFromMailboxPath(mailboxPath, Optional.empty(), mailboxSession).block();
assertThat(id).contains(parentId);
}
@@ -185,7 +187,7 @@ public class MailboxFactoryTest {
.count(0)
.unseen(0)
.build()))),
- mailboxSession);
+ mailboxSession).block();
assertThat(id).contains(parentId);
}
@@ -198,7 +200,7 @@ public class MailboxFactoryTest {
.id(mailboxId.get())
.session(mailboxSession)
.build()
- .get();
+ .block();
assertThat(retrievedMailbox.getNamespace())
.isEqualTo(MailboxNamespace.personal());
@@ -227,7 +229,7 @@ public class MailboxFactoryTest {
.unseen(0)
.build()))))
.build()
- .get();
+ .block();
assertThat(retrievedMailbox.getParentId())
.contains(preLoadedId);
@@ -248,7 +250,7 @@ public class MailboxFactoryTest {
.id(mailboxId.get())
.session(otherMailboxSession)
.build()
- .get();
+ .block();
assertThat(retrievedMailbox.getNamespace())
.isEqualTo(MailboxNamespace.delegated(user));
@@ -263,7 +265,7 @@ public class MailboxFactoryTest {
.id(mailboxId.get())
.session(mailboxSession)
.build()
- .get();
+ .block();
softly.assertThat(retrievedMailbox.isMayAddItems()).isTrue();
softly.assertThat(retrievedMailbox.isMayCreateChild()).isTrue();
@@ -288,7 +290,7 @@ public class MailboxFactoryTest {
.id(mailboxId.get())
.session(otherMailboxSession)
.build()
- .get();
+ .block();
softly.assertThat(retrievedMailbox.isMayAddItems()).isTrue();
softly.assertThat(retrievedMailbox.isMayCreateChild()).isFalse();
@@ -313,7 +315,7 @@ public class MailboxFactoryTest {
.id(mailboxId.get())
.session(otherMailboxSession)
.build()
- .get();
+ .block();
softly.assertThat(retrievedMailbox.isMayAddItems()).isFalse();
softly.assertThat(retrievedMailbox.isMayCreateChild()).isFalse();
@@ -338,7 +340,7 @@ public class MailboxFactoryTest {
.id(mailboxId.get())
.session(otherMailboxSession)
.build()
- .get();
+ .block();
softly.assertThat(retrievedMailbox.isMayAddItems()).isFalse();
softly.assertThat(retrievedMailbox.isMayCreateChild()).isFalse();
@@ -367,7 +369,8 @@ public class MailboxFactoryTest {
Optional<Mailbox> mailbox = sut.builder()
.mailboxMetadata(metaData)
.session(mailboxSession)
- .build();
+ .build()
+ .blockOptional();
softly.assertThat(mailbox).isPresent();
softly.assertThat(mailbox).map(Mailbox::getId).contains(metaData.getId());
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
index ac2e32d..6f08d44 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
@@ -107,8 +107,7 @@ class EmailQueryMethod @Inject() (serializer: EmailQuerySerializer,
val condition: FilterCondition = request.filter.get.asInstanceOf[FilterCondition]
val mailboxId: MailboxId = condition.inMailbox.get
val after: ZonedDateTime = condition.after.get.asUTC
- SMono.fromCallable(() => mailboxManager.getMailbox(mailboxId, mailboxSession))
- .subscribeOn(Schedulers.elastic())
+ SMono(mailboxManager.getMailboxReactive(mailboxId, mailboxSession))
.`then`(SFlux.fromPublisher(
emailQueryView.listMailboxContentSinceReceivedAt(mailboxId, after, JavaLimit.from(limitToUse.value)))
.drop(position.value)
@@ -122,8 +121,7 @@ class EmailQueryMethod @Inject() (serializer: EmailQuerySerializer,
private def queryViewForListingSortedBySentAt(mailboxSession: MailboxSession, position: Position, limitToUse: Limit, request: EmailQueryRequest): SMono[Seq[MessageId]] = {
val mailboxId: MailboxId = request.filter.get.asInstanceOf[FilterCondition].inMailbox.get
- SMono.fromCallable(() => mailboxManager.getMailbox(mailboxId, mailboxSession))
- .subscribeOn(Schedulers.elastic())
+ SMono(mailboxManager.getMailboxReactive(mailboxId, mailboxSession))
.`then`(SFlux.fromPublisher(
emailQueryView.listMailboxContent(mailboxId, JavaLimit.from(limitToUse.value)))
.drop(position.value)
diff --git a/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/EmailQueryViewPopulator.java b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/EmailQueryViewPopulator.java
index 2ea9f16..7a77db5 100644
--- a/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/EmailQueryViewPopulator.java
+++ b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/EmailQueryViewPopulator.java
@@ -189,8 +189,7 @@ public class EmailQueryViewPopulator {
}
private Mono<MessageManager> retrieveMailbox(MailboxSession session, MailboxMetaData mailboxMetadata) {
- return Mono.fromCallable(() -> mailboxManager.getMailbox(mailboxMetadata.getId(), session))
- .subscribeOn(Schedulers.elastic());
+ return Mono.from(mailboxManager.getMailboxReactive(mailboxMetadata.getId(), session));
}
private Flux<MessageResult> listAllMessages(MessageManager messageManager, MailboxSession session) {
diff --git a/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/MessageFastViewProjectionCorrector.java b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/MessageFastViewProjectionCorrector.java
index da0a6d7..054f85d 100644
--- a/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/MessageFastViewProjectionCorrector.java
+++ b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/MessageFastViewProjectionCorrector.java
@@ -211,8 +211,7 @@ public class MessageFastViewProjectionCorrector {
}
private Mono<MessageManager> retrieveMailbox(MailboxSession session, MailboxMetaData mailboxMetadata) {
- return Mono.fromCallable(() -> mailboxManager.getMailbox(mailboxMetadata.getId(), session))
- .subscribeOn(Schedulers.elastic());
+ return Mono.from(mailboxManager.getMailboxReactive(mailboxMetadata.getId(), session));
}
private Flux<ComposedMessageIdWithMetaData> listAllMailboxMessages(MessageManager messageManager, MailboxSession session) {
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org