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/06/30 01:07:13 UTC

[james-project] 02/06: [PERFORMANCE] Fasten Mailbox/get by ids

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 482e770d97f7e2af8c88cdf0154bd3e5acde9413
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sun Jun 27 12:20:12 2021 +0700

    [PERFORMANCE] Fasten Mailbox/get by ids
    
     - Load quotas only once
    
    Was loaded for each id...
    
     - Shortcut on emtpy Ids
    
    This happens for instance when chaining /changes and /get with backreference.
    
    We can save on subscriptions / quota loading...
---
 .../org/apache/james/jmap/mail/MailboxGet.scala    |  4 +++
 .../james/jmap/method/MailboxGetMethod.scala       | 34 +++++++++++++---------
 2 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala
index af866cd..2666989 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala
@@ -47,6 +47,10 @@ object MailboxGet {
 
 case class UnparsedMailboxId(id: Id)
 
+object Ids {
+  val EMPTY = Ids(List())
+}
+
 case class Ids(value: List[UnparsedMailboxId])
 
 case class MailboxGetRequest(accountId: AccountId,
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala
index ca9b2e1..9a62ca9 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala
@@ -28,7 +28,7 @@ import org.apache.james.jmap.core.Invocation.{Arguments, MethodName}
 import org.apache.james.jmap.core.{AccountId, CapabilityIdentifier, ErrorCode, Invocation, Properties, UuidState}
 import org.apache.james.jmap.http.MailboxesProvisioner
 import org.apache.james.jmap.json.{MailboxSerializer, ResponseSerializer}
-import org.apache.james.jmap.mail.{Mailbox, MailboxFactory, MailboxGet, MailboxGetRequest, MailboxGetResponse, NotFound, PersonalNamespace, Subscriptions, UnparsedMailboxId}
+import org.apache.james.jmap.mail.{Ids, Mailbox, MailboxFactory, MailboxGet, MailboxGetRequest, MailboxGetResponse, NotFound, PersonalNamespace, Subscriptions, UnparsedMailboxId}
 import org.apache.james.jmap.routes.SessionSupplier
 import org.apache.james.jmap.utils.quotas.{QuotaLoaderWithPreloadedDefault, QuotaLoaderWithPreloadedDefaultFactory}
 import org.apache.james.mailbox.exception.MailboxNotFoundException
@@ -115,13 +115,19 @@ class MailboxGetMethod @Inject() (serializer: MailboxSerializer,
         mailboxGetRequest.ids match {
           case None => getAllMailboxes(capabilities, mailboxSession)
             .map(MailboxGetResults.found)
+          case Some(Ids.EMPTY) => SFlux.empty
           case Some(ids) =>
-            retrieveSubscriptions(mailboxSession)
-              .flatMapMany(subscriptions => SFlux.fromIterable(ids.value)
-                .flatMap(id => Try(mailboxIdFactory.fromString(id.id))
-                  .fold(e => SMono.just(MailboxGetResults.notFound(id)),
-                    mailboxId => getMailboxResultById(capabilities, mailboxId, subscriptions, mailboxSession)),
-                  maxConcurrency = 5))
+            SMono.zip(array => (array(0).asInstanceOf[QuotaLoaderWithPreloadedDefault],
+              array(1).asInstanceOf[Subscriptions]),
+              quotaFactory.loadFor(mailboxSession),
+              retrieveSubscriptions(mailboxSession))
+              .flatMapMany {
+                case (quotaLoader, subscriptions) => SFlux.fromIterable(ids.value)
+                  .flatMap(id => Try(mailboxIdFactory.fromString(id.id))
+                    .fold(e => SMono.just(MailboxGetResults.notFound(id)),
+                      mailboxId => getMailboxResultById(capabilities, mailboxId, subscriptions, quotaLoader, mailboxSession)),
+                    maxConcurrency = 5)
+              }
         })
 
   private def retrieveSubscriptions(mailboxSession: MailboxSession): SMono[Subscriptions] =
@@ -132,14 +138,14 @@ class MailboxGetMethod @Inject() (serializer: MailboxSerializer,
   private def getMailboxResultById(capabilities: Set[CapabilityIdentifier],
                                    mailboxId: MailboxId,
                                    subscriptions: Subscriptions,
+                                   quotaLoader: QuotaLoaderWithPreloadedDefault,
                                    mailboxSession: MailboxSession): SMono[MailboxGetResults] =
-    quotaFactory.loadFor(mailboxSession)
-      .flatMap(quotaLoader => mailboxFactory.create(mailboxId, mailboxSession, quotaLoader, subscriptions)
-        .map(mailbox => filterShared(capabilities, mailbox))
-        .onErrorResume {
-          case _: MailboxNotFoundException => SMono.just(MailboxGetResults.notFound(mailboxId))
-          case error => SMono.error(error)
-        })
+    mailboxFactory.create(mailboxId, mailboxSession, quotaLoader, subscriptions)
+      .map(mailbox => filterShared(capabilities, mailbox))
+      .onErrorResume {
+        case _: MailboxNotFoundException => SMono.just(MailboxGetResults.notFound(mailboxId))
+        case error => SMono.error(error)
+      }
       .subscribeOn(Schedulers.elastic)
 
   private def filterShared(capabilities: Set[CapabilityIdentifier], mailbox: Mailbox): MailboxGetResults = {

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org