You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2020/04/02 04:32:07 UTC

[james-project] branch master updated (30092e6 -> f08f82f)

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git.


    from 30092e6  Write an ADR about James polyglot strategy
     new cdc9304  [Build] Fasten JMAP Draft memory integration testing
     new ed3b695  [Performance] Avoid loading mailbox counters for getAllReadableMailboxes
     new 5e670d1  JAMES-2632 Lazy loading for backend parentId computation
     new a8b84c4  JAMES-2632 Avoid reading MailboxPathV1Table if not needed
     new 948252e  JAMES-2632 Add a MailboxPath::child method
     new c84c807  JAMES-2648 Avoid reading schemaVersion upon each alias resolution
     new 984dc0f  JAMES-2648 Rely on CassandraSchemaVersionManager for version computation
     new 5259710  JAMES-2648 Avoid reading schemaVersion upon each alias resolution
     new dcc7583  JAMES-2648 Add a CassandraVersionManager::isBefore with initial state caching
     new b426d6b  JAMES-3105 Staged builder for mailbox counters
     new ee4510b  JAMES-3105 Additional sanitizing for mailbox counters
     new 8d756d9  JAMES-3078 Allow writting reactive methods
     new 30f600a  JAMES-3078 Reactify GetVacation
     new 653525c  JAMES-3078 Reactify SetVacation
     new f08f82f  JAMES-3078 MDC hierarchical MDC context for reactor

The 15 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../versions/CassandraSchemaVersionManager.java    |   9 ++
 .../CassandraSchemaVersionManagerTest.java         |  48 +++++++
 .../james/mailbox/model/MailboxCounters.java       |  80 ++++++++---
 .../apache/james/mailbox/model/MailboxPath.java    |   9 ++
 .../james/mailbox/model/MailboxCountersTest.java   |  64 +++++++++
 .../james/mailbox/model/MailboxPathTest.java       |  28 ++++
 .../CassandraMailboxSessionMapperFactory.java      |   7 +-
 .../cassandra/mail/CassandraMailboxCounterDAO.java |   2 +-
 .../cassandra/mail/CassandraMailboxMapper.java     |  36 ++++-
 .../CassandraSubscriptionManagerTest.java          |   3 +
 .../mail/CassandraMailboxCounterDAOTest.java       |  28 ++--
 .../mail/CassandraMailboxMapperGenericTest.java    |  40 ++++--
 .../cassandra/mail/CassandraMailboxMapperTest.java |   4 +-
 .../mail/migration/MailboxPathV2MigrationTest.java |   4 +-
 .../james/mailbox/store/StoreMailboxManager.java   |  28 ++--
 .../james/mailbox/store/StoreMessageManager.java   |   2 +-
 .../james/imap/processor/UnselectProcessor.java    |   3 +-
 .../modules/mailbox/FastRetryBackoffModule.java}   |  16 ++-
 .../container/guice/protocols/jmap-draft/pom.xml   |   4 +
 .../apache/james/modules/TestJMAPServerModule.java |   5 +
 .../java/org/apache/james/util/MDCBuilder.java     |   5 +
 .../java/org/apache/james/util/ReactorUtils.java   |  50 +++++++
 .../org/apache/james/util/ReactorUtilsTest.java    |  50 +++++++
 .../cassandra/CassandraRecipientRewriteTable.java  |  17 +--
 .../CassandraRecipientRewriteTableV6Test.java      |  16 +--
 ...draRecipientRewriteTableV7BeforeStartTest.java} |  19 ++-
 .../CassandraRecipientRewriteTableV7Test.java      |  11 +-
 .../james/rrt/cassandra/CassandraStepdefs.java     |   6 +-
 .../james/jmap/draft/methods/GetFilterMethod.java  |   2 +-
 .../jmap/draft/methods/GetMailboxesMethod.java     |   2 +-
 .../jmap/draft/methods/GetMessageListMethod.java   |   4 +-
 .../jmap/draft/methods/GetMessagesMethod.java      |   2 +-
 .../draft/methods/GetVacationResponseMethod.java   |  33 +++--
 .../jmap/draft/methods/JmapResponseWriter.java     |   6 +-
 .../jmap/draft/methods/JmapResponseWriterImpl.java |   5 +-
 .../apache/james/jmap/draft/methods/Method.java    |  16 ++-
 .../james/jmap/draft/methods/RequestHandler.java   |  22 +--
 .../james/jmap/draft/methods/SetFilterMethod.java  |   2 +-
 .../jmap/draft/methods/SetMailboxesMethod.java     |   2 +-
 .../jmap/draft/methods/SetMessagesMethod.java      |   2 +-
 .../draft/methods/SetVacationResponseMethod.java   |  46 +++---
 .../james/jmap/draft/model/MailboxFactory.java     |   9 +-
 .../james/jmap/http/AuthenticationRoutes.java      |  57 +++++---
 .../org/apache/james/jmap/http/DownloadRoutes.java |  22 ++-
 .../org/apache/james/jmap/http/JMAPApiRoutes.java  |  24 ++--
 ...henticationStrategy.java => LoggingHelper.java} |  28 ++--
 .../org/apache/james/jmap/http/UploadRoutes.java   |  12 +-
 .../jmap/draft/methods/GetMailboxesMethodTest.java |  24 ++--
 .../jmap/draft/methods/GetMessagesMethodTest.java  |  46 +++---
 .../methods/GetVacationResponseMethodTest.java     |   6 +-
 .../draft/methods/JmapResponseWriterImplTest.java  | 155 +++++++++++----------
 .../jmap/draft/methods/RequestHandlerTest.java     |   7 +-
 .../jmap/draft/methods/SetMailboxesMethodTest.java |  12 +-
 .../methods/SetVacationResponseMethodTest.java     |  18 +--
 .../james/jmap/draft/model/MailboxFactoryTest.java |  32 ++++-
 .../apache/james/jmap/http/JMAPApiRoutesTest.java  |  14 +-
 .../java/org/apache/james/jmap/JMAPRoutes.java     |   1 -
 .../vault/DeletedMessageVaultIntegrationTest.java  |   4 +-
 .../org/apache/james/jmap/JmapCommonRequests.java  |   4 +-
 59 files changed, 839 insertions(+), 374 deletions(-)
 copy server/container/guice/{jpa-guice/src/main/java/org/apache/james/modules/mailbox/JPAQuotaSearchModule.java => mailbox/src/main/java/org/apache/james/modules/mailbox/FastRetryBackoffModule.java} (76%)
 copy server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/{CassandraRecipientRewriteTableV7Test.java => CassandraRecipientRewriteTableV7BeforeStartTest.java} (88%)
 copy server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/{AuthenticationStrategy.java => LoggingHelper.java} (64%)


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


[james-project] 09/15: JAMES-2648 Add a CassandraVersionManager::isBefore with initial state caching

Posted by bt...@apache.org.
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 dcc7583119a4025ebc7b8d3ce3ddfaf7216562bc
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Mar 31 14:59:03 2020 +0700

    JAMES-2648 Add a CassandraVersionManager::isBefore with initial state caching
---
 .../versions/CassandraSchemaVersionManager.java    |  9 ++++
 .../CassandraSchemaVersionManagerTest.java         | 48 ++++++++++++++++++++++
 .../cassandra/CassandraRecipientRewriteTable.java  | 15 +------
 3 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManager.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManager.java
index 37a222d..ef56bdb 100644
--- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManager.java
+++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManager.java
@@ -41,6 +41,7 @@ public class CassandraSchemaVersionManager {
 
     private final SchemaVersion minVersion;
     private final SchemaVersion maxVersion;
+    private final SchemaVersion initialSchemaVersion;
     private final CassandraSchemaVersionDAO schemaVersionDAO;
 
     public enum SchemaState {
@@ -63,6 +64,14 @@ public class CassandraSchemaVersionManager {
         this.schemaVersionDAO = schemaVersionDAO;
         this.minVersion = minVersion;
         this.maxVersion = maxVersion;
+
+        this.initialSchemaVersion = computeVersion();
+    }
+
+    public boolean isBefore(SchemaVersion minimum) {
+        return initialSchemaVersion.isBefore(minimum)
+            // If we started with a legacy james then maybe schema version had been updated since then
+            && computeVersion().isBefore(minimum);
     }
 
     public SchemaVersion computeVersion() {
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManagerTest.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManagerTest.java
index 852fcce..64c498e 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManagerTest.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManagerTest.java
@@ -63,6 +63,54 @@ class CassandraSchemaVersionManagerTest {
     }
 
     @Test
+    void isBeforeShouldReturnTrueWhenBefore() {
+        SchemaVersion currentVersion = minVersion;
+
+        when(schemaVersionDAO.getCurrentSchemaVersion())
+            .thenReturn(Mono.just(Optional.of(currentVersion)));
+
+        CassandraSchemaVersionManager testee = new CassandraSchemaVersionManager(
+            schemaVersionDAO,
+            minVersion,
+            maxVersion);
+
+        assertThat(testee.isBefore(maxVersion)).isTrue();
+    }
+
+    @Test
+    void isBeforeShouldReturnFalseWhenEquals() {
+        SchemaVersion currentVersion = maxVersion;
+
+        when(schemaVersionDAO.getCurrentSchemaVersion())
+            .thenReturn(Mono.just(Optional.of(currentVersion)));
+
+        CassandraSchemaVersionManager testee = new CassandraSchemaVersionManager(
+            schemaVersionDAO,
+            minVersion,
+            maxVersion);
+
+        assertThat(testee.isBefore(maxVersion)).isFalse();
+    }
+
+    @Test
+    void isBeforeShouldReturnFalseWhenUpdatedToEquals() {
+        SchemaVersion currentVersion = maxVersion;
+
+        when(schemaVersionDAO.getCurrentSchemaVersion())
+            .thenReturn(Mono.just(Optional.of(minVersion)));
+
+        CassandraSchemaVersionManager testee = new CassandraSchemaVersionManager(
+            schemaVersionDAO,
+            minVersion,
+            maxVersion);
+
+        when(schemaVersionDAO.getCurrentSchemaVersion())
+            .thenReturn(Mono.just(Optional.of(maxVersion)));
+
+        assertThat(testee.isBefore(maxVersion)).isFalse();
+    }
+
+    @Test
     void computeSchemaStateShouldReturnTooOldWhenVersionIsMoreThanMaxVersion() {
         SchemaVersion currentVersion = maxVersion.next();
 
diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
index 0eac424..6dc233b 100644
--- a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
@@ -43,7 +43,6 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
     private final CassandraRecipientRewriteTableDAO cassandraRecipientRewriteTableDAO;
     private final CassandraMappingsSourcesDAO cassandraMappingsSourcesDAO;
     private final CassandraSchemaVersionManager versionManager;
-    private final SchemaVersion initialSchemaVersion;
 
     @Inject
     CassandraRecipientRewriteTable(CassandraRecipientRewriteTableDAO cassandraRecipientRewriteTableDAO,
@@ -52,8 +51,6 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
         this.cassandraRecipientRewriteTableDAO = cassandraRecipientRewriteTableDAO;
         this.cassandraMappingsSourcesDAO = cassandraMappingsSourcesDAO;
         this.versionManager = versionManager;
-
-        initialSchemaVersion = versionManager.computeVersion();
     }
 
     @Override
@@ -100,20 +97,10 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
         Preconditions.checkArgument(listSourcesSupportedType.contains(mapping.getType()),
             "Not supported mapping of type %s", mapping.getType());
 
-        if (isLegacy()) {
+        if (versionManager.isBefore(MAPPINGS_SOURCES_SUPPORTED_VERSION)) {
             return super.listSources(mapping);
         }
 
         return cassandraMappingsSourcesDAO.retrieveSources(mapping).toStream();
     }
-
-    private boolean isLegacy() {
-        return isLegacy(initialSchemaVersion)
-            // If we started with a legacy james then maybe schema version had been updated since then
-            && isLegacy(versionManager.computeVersion());
-    }
-
-    private boolean isLegacy(SchemaVersion schemaVersion) {
-        return schemaVersion.isBefore(MAPPINGS_SOURCES_SUPPORTED_VERSION);
-    }
 }


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


[james-project] 12/15: JAMES-3078 Allow writting reactive methods

Posted by bt...@apache.org.
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 8d756d9bd4ff58b6e66283c5c03300dcc488e4f2
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sun Mar 22 18:03:17 2020 +0700

    JAMES-3078 Allow writting reactive methods
---
 .../james/jmap/draft/methods/GetFilterMethod.java  |   2 +-
 .../jmap/draft/methods/GetMailboxesMethod.java     |   2 +-
 .../jmap/draft/methods/GetMessageListMethod.java   |   4 +-
 .../jmap/draft/methods/GetMessagesMethod.java      |   2 +-
 .../draft/methods/GetVacationResponseMethod.java   |   2 +-
 .../jmap/draft/methods/JmapResponseWriter.java     |   6 +-
 .../jmap/draft/methods/JmapResponseWriterImpl.java |   5 +-
 .../apache/james/jmap/draft/methods/Method.java    |  16 ++-
 .../james/jmap/draft/methods/RequestHandler.java   |  22 +--
 .../james/jmap/draft/methods/SetFilterMethod.java  |   2 +-
 .../jmap/draft/methods/SetMailboxesMethod.java     |   2 +-
 .../jmap/draft/methods/SetMessagesMethod.java      |   2 +-
 .../draft/methods/SetVacationResponseMethod.java   |   2 +-
 .../org/apache/james/jmap/http/JMAPApiRoutes.java  |   8 +-
 .../jmap/draft/methods/GetMailboxesMethodTest.java |  24 ++--
 .../jmap/draft/methods/GetMessagesMethodTest.java  |  46 +++---
 .../methods/GetVacationResponseMethodTest.java     |   6 +-
 .../draft/methods/JmapResponseWriterImplTest.java  | 155 +++++++++++----------
 .../jmap/draft/methods/RequestHandlerTest.java     |   7 +-
 .../jmap/draft/methods/SetMailboxesMethodTest.java |  12 +-
 .../methods/SetVacationResponseMethodTest.java     |  18 +--
 .../apache/james/jmap/http/JMAPApiRoutesTest.java  |   5 +-
 22 files changed, 185 insertions(+), 165 deletions(-)

diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java
index 390fb69..5bb238c 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java
@@ -65,7 +65,7 @@ public class GetFilterMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(methodCallId);
         Preconditions.checkNotNull(mailboxSession);
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 375524f..da0ad86 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
@@ -88,7 +88,7 @@ public class GetMailboxesMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkArgument(request instanceof GetMailboxesRequest);
         GetMailboxesRequest mailboxesRequest = (GetMailboxesRequest) request;
 
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 eb6e66e..19c7503 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
@@ -89,7 +89,7 @@ public class GetMessageListMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkArgument(request instanceof GetMessageListRequest);
 
         GetMessageListRequest messageListRequest = (GetMessageListRequest) request;
@@ -180,7 +180,7 @@ public class GetMessageListMethod implements Method {
                     .ids(messageListResponse.getMessageIds())
                     .properties(messageListRequest.getFetchMessageProperties())
                     .build();
-            return getMessagesMethod.process(getMessagesRequest, methodCallId, mailboxSession);
+            return getMessagesMethod.processToStream(getMessagesRequest, methodCallId, mailboxSession);
         }
         return Stream.empty();
     }
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java
index 383455e..d16367f 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java
@@ -81,7 +81,7 @@ public class GetMessagesMethod implements Method {
     }
     
     @Override
-    public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(mailboxSession);
         Preconditions.checkArgument(request instanceof GetMessagesRequest);
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
index 6717312..18c3017 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
@@ -64,7 +64,7 @@ public class GetVacationResponseMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(methodCallId);
         Preconditions.checkNotNull(mailboxSession);
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/JmapResponseWriter.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/JmapResponseWriter.java
index fcf4bd3..2bd49a2 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/JmapResponseWriter.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/JmapResponseWriter.java
@@ -19,12 +19,12 @@
 
 package org.apache.james.jmap.draft.methods;
 
-import java.util.stream.Stream;
-
 import org.apache.james.jmap.draft.model.InvocationResponse;
 
+import reactor.core.publisher.Flux;
+
 public interface JmapResponseWriter {
 
-    Stream<InvocationResponse> formatMethodResponse(Stream<JmapResponse> jmapResponse);
+    Flux<InvocationResponse> formatMethodResponse(Flux<JmapResponse> jmapResponse);
 
 }
\ No newline at end of file
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/JmapResponseWriterImpl.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/JmapResponseWriterImpl.java
index 13a043c..a0e1dd8 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/JmapResponseWriterImpl.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/JmapResponseWriterImpl.java
@@ -21,7 +21,6 @@ package org.apache.james.jmap.draft.methods;
 
 import java.util.Optional;
 import java.util.Set;
-import java.util.stream.Stream;
 
 import javax.inject.Inject;
 
@@ -36,6 +35,8 @@ import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
 import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
 import com.github.steveash.guavate.Guavate;
 
+import reactor.core.publisher.Flux;
+
 public class JmapResponseWriterImpl implements JmapResponseWriter {
 
     public static final String PROPERTIES_FILTER = "propertiesFilter";
@@ -47,7 +48,7 @@ public class JmapResponseWriterImpl implements JmapResponseWriter {
     }
 
     @Override
-    public Stream<InvocationResponse> formatMethodResponse(Stream<JmapResponse> jmapResponses) {
+    public Flux<InvocationResponse> formatMethodResponse(Flux<JmapResponse> jmapResponses) {
         return jmapResponses.map(jmapResponse -> {
             ObjectMapper objectMapper = newConfiguredObjectMapper(jmapResponse);
 
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/Method.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/Method.java
index 62909b6..564f6de 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/Method.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/Method.java
@@ -30,6 +30,10 @@ import org.apache.james.mailbox.MailboxSession;
 import com.fasterxml.jackson.annotation.JsonValue;
 import com.google.common.base.Preconditions;
 
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
+
 public interface Method {
 
     String JMAP_PREFIX = "JMAP-";
@@ -123,7 +127,15 @@ public interface Method {
     Request.Name requestHandled();
 
     Class<? extends JmapRequest> requestType();
-    
-    Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession);
 
+    default Flux<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+        return Mono.fromCallable(() -> processToStream(request, methodCallId, mailboxSession))
+            .flatMapMany(Flux::fromStream)
+            .subscribeOn(Schedulers.elastic());
+    }
+
+    default Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+        return process(request, methodCallId, mailboxSession)
+            .toStream();
+    }
 }
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/RequestHandler.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/RequestHandler.java
index 261c06f..2b71839 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/RequestHandler.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/RequestHandler.java
@@ -26,7 +26,6 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import javax.inject.Inject;
 
@@ -39,6 +38,8 @@ import org.apache.james.util.MDCBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import reactor.core.publisher.Flux;
+
 public class RequestHandler {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class);
@@ -55,7 +56,7 @@ public class RequestHandler {
                 .collect(Collectors.toMap(Method::requestHandled, Function.identity()));
     }
 
-    public Stream<InvocationResponse> handle(AuthenticatedRequest request) throws IOException {
+    public Flux<InvocationResponse> handle(AuthenticatedRequest request) {
         Optional<MailboxSession> mailboxSession = Optional.ofNullable(request.getMailboxSession());
         try (Closeable closeable =
                  MDCBuilder.create()
@@ -67,23 +68,24 @@ public class RequestHandler {
                 .map(extractAndProcess(request))
                 .map(jmapResponseWriter::formatMethodResponse)
                 .orElseThrow(() -> new IllegalStateException("unknown method " + request.getMethodName()));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
         }
     }
     
-    private Function<Method, Stream<JmapResponse>> extractAndProcess(AuthenticatedRequest request) {
+    private Function<Method, Flux<JmapResponse>> extractAndProcess(AuthenticatedRequest request) {
         MailboxSession mailboxSession = request.getMailboxSession();
         return (Method method) -> {
                     try {
                         JmapRequest jmapRequest = jmapRequestParser.extractJmapRequest(request, method.requestType());
-                        return method.process(jmapRequest, request.getMethodCallId(), mailboxSession);
+                        return method.process(jmapRequest, request.getMethodCallId(), mailboxSession)
+                            .onErrorResume(JmapFieldNotSupportedException.class, e -> errorNotImplemented(e, request));
                     } catch (IOException e) {
                         LOGGER.error("Error occured while parsing the request.", e);
                         if (e.getCause() instanceof JmapFieldNotSupportedException) {
                             return errorNotImplemented((JmapFieldNotSupportedException) e.getCause(), request);
                         }
                         return error(request, generateInvalidArgumentError(e.getMessage()));
-                    } catch (JmapFieldNotSupportedException e) {
-                        return errorNotImplemented(e, request);
                     }
                 };
     }
@@ -95,16 +97,16 @@ public class RequestHandler {
             .build();
     }
 
-    private Stream<JmapResponse> errorNotImplemented(JmapFieldNotSupportedException error, AuthenticatedRequest request) {
-        return Stream.of(
+    private Flux<JmapResponse> errorNotImplemented(JmapFieldNotSupportedException error, AuthenticatedRequest request) {
+        return Flux.just(
                 JmapResponse.builder()
                     .methodCallId(request.getMethodCallId())
                     .error(generateInvalidArgumentError("The field '" + error.getField() + "' of '" + error.getIssuer() + "' is not supported"))
                     .build());
     }
 
-    private Stream<JmapResponse> error(AuthenticatedRequest request, ErrorResponse error) {
-        return Stream.of(
+    private Flux<JmapResponse> error(AuthenticatedRequest request, ErrorResponse error) {
+        return Flux.just(
                 JmapResponse.builder()
                     .methodCallId(request.getMethodCallId())
                     .error(error)
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetFilterMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetFilterMethod.java
index 2cf6523..b6e82d7 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetFilterMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetFilterMethod.java
@@ -102,7 +102,7 @@ public class SetFilterMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(methodCallId);
         Preconditions.checkNotNull(mailboxSession);
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesMethod.java
index 56f6ed9..32291fe 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesMethod.java
@@ -59,7 +59,7 @@ public class SetMailboxesMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(methodCallId);
         Preconditions.checkNotNull(mailboxSession);
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesMethod.java
index 886896d..dd7b385 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesMethod.java
@@ -59,7 +59,7 @@ public class SetMessagesMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkArgument(request instanceof SetMessagesRequest);
         SetMessagesRequest setMessagesRequest = (SetMessagesRequest) request;
 
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
index 0f11529..215223c 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
@@ -69,7 +69,7 @@ public class SetVacationResponseMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(methodCallId);
         Preconditions.checkNotNull(mailboxSession);
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JMAPApiRoutes.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JMAPApiRoutes.java
index bbe3269..9973616 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JMAPApiRoutes.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JMAPApiRoutes.java
@@ -104,7 +104,7 @@ public class JMAPApiRoutes implements JMAPRoutes {
             requestAsJsonStream(request)
                 .map(InvocationRequest::deserialize)
                 .map(invocationRequest -> AuthenticatedRequest.decorate(invocationRequest, session))
-                .concatMap(this::handle)
+                .concatMap(requestHandler::handle)
                 .map(InvocationResponse::asProtocolSpecification);
 
         return sendResponses(response, responses);
@@ -125,12 +125,6 @@ public class JMAPApiRoutes implements JMAPRoutes {
                 .then());
     }
 
-    private Flux<? extends InvocationResponse> handle(AuthenticatedRequest request) {
-        return Mono.fromCallable(() -> requestHandler.handle(request))
-            .flatMapMany(Flux::fromStream)
-            .subscribeOn(Schedulers.elastic());
-    }
-
     private Flux<JsonNode[]> requestAsJsonStream(HttpServerRequest req) {
         return req.receive().aggregate().asInputStream()
             .map(inputStream -> {
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMailboxesMethodTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMailboxesMethodTest.java
index 2ac5c67..f0b9cca 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMailboxesMethodTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMailboxesMethodTest.java
@@ -88,7 +88,7 @@ public class GetMailboxesMethodTest {
 
         MailboxSession mailboxSession = mailboxManager.createSystemSession(USERNAME);
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -112,7 +112,7 @@ public class GetMailboxesMethodTest {
                 .build();
         MailboxSession session = MailboxSessionUtil.create(USERNAME);
 
-        List<JmapResponse> getMailboxesResponse = testee.process(getMailboxesRequest, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = testee.processToStream(getMailboxesRequest, methodCallId, session).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -142,7 +142,7 @@ public class GetMailboxesMethodTest {
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -167,7 +167,7 @@ public class GetMailboxesMethodTest {
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, userSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, userSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -188,7 +188,7 @@ public class GetMailboxesMethodTest {
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -209,7 +209,7 @@ public class GetMailboxesMethodTest {
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -230,7 +230,7 @@ public class GetMailboxesMethodTest {
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -258,7 +258,7 @@ public class GetMailboxesMethodTest {
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -288,7 +288,7 @@ public class GetMailboxesMethodTest {
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -318,7 +318,7 @@ public class GetMailboxesMethodTest {
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -357,7 +357,7 @@ public class GetMailboxesMethodTest {
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
@@ -387,7 +387,7 @@ public class GetMailboxesMethodTest {
         GetMailboxesRequest getMailboxesRequest = GetMailboxesRequest.builder()
                 .build();
 
-        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.process(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
+        List<JmapResponse> getMailboxesResponse = getMailboxesMethod.processToStream(getMailboxesRequest, methodCallId, mailboxSession).collect(Collectors.toList());
 
         assertThat(getMailboxesResponse)
                 .hasSize(1)
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMessagesMethodTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMessagesMethodTest.java
index 35c2bcc..41b2ad1 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMessagesMethodTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMessagesMethodTest.java
@@ -155,24 +155,24 @@ public class GetMessagesMethodTest {
     @Test
     public void processShouldThrowWhenNullRequest() {
         GetMessagesRequest request = null;
-        assertThatThrownBy(() -> testee.process(request, mock(MethodCallId.class), mock(MailboxSession.class))).isInstanceOf(NullPointerException.class);
+        assertThatThrownBy(() -> testee.processToStream(request, mock(MethodCallId.class), mock(MailboxSession.class))).isInstanceOf(NullPointerException.class);
     }
 
     @Test
     public void processShouldThrowWhenNullSession() {
         MailboxSession mailboxSession = null;
-        assertThatThrownBy(() -> testee.process(mock(GetMessagesRequest.class), mock(MethodCallId.class), mailboxSession)).isInstanceOf(NullPointerException.class);
+        assertThatThrownBy(() -> testee.processToStream(mock(GetMessagesRequest.class), mock(MethodCallId.class), mailboxSession)).isInstanceOf(NullPointerException.class);
     }
 
     @Test
     public void processShouldThrowWhenNullMethodCallId() {
         MethodCallId methodCallId = null;
-        assertThatThrownBy(() -> testee.process(mock(GetMessagesRequest.class), methodCallId, mock(MailboxSession.class))).isInstanceOf(NullPointerException.class);
+        assertThatThrownBy(() -> testee.processToStream(mock(GetMessagesRequest.class), methodCallId, mock(MailboxSession.class))).isInstanceOf(NullPointerException.class);
     }
 
     @Test
     public void processShouldThrowWhenRequestHasAccountId() {
-        assertThatThrownBy(() -> testee.process(
+        assertThatThrownBy(() -> testee.processToStream(
             GetMessagesRequest.builder().accountId("abc").build(), mock(MethodCallId.class), mock(MailboxSession.class))).isInstanceOf(NotImplementedException.class);
     }
 
@@ -190,7 +190,7 @@ public class GetMessagesMethodTest {
                 message3.getMessageId()))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
             .extracting(JmapResponse::getResponse)
@@ -221,7 +221,7 @@ public class GetMessagesMethodTest {
             .ids(ImmutableList.of(message.getMessageId()))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
             .extracting(JmapResponse::getResponse)
@@ -244,7 +244,7 @@ public class GetMessagesMethodTest {
             .properties(ImmutableList.of())
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1);
         assertThat(result.get(0).getProperties())
@@ -261,7 +261,7 @@ public class GetMessagesMethodTest {
             .ids(ImmutableList.of(message1.getMessageId()))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
         assertThat(result).hasSize(1);
         assertThat(result.get(0).getProperties())
             .isEqualTo(Optional.of(MessageProperty.allOutputProperties()));
@@ -280,7 +280,7 @@ public class GetMessagesMethodTest {
 
         Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.subject);
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
         assertThat(result).hasSize(1);
         assertThat(result.get(0).getProperties())
             .isEqualTo(Optional.of(expected));
@@ -299,7 +299,7 @@ public class GetMessagesMethodTest {
 
         Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.textBody);
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1);
         assertThat(result.get(0).getProperties())
@@ -322,7 +322,7 @@ public class GetMessagesMethodTest {
             .ids(ImmutableList.of(message.getMessageId()))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
             .extracting(JmapResponse::getResponse)
@@ -350,7 +350,7 @@ public class GetMessagesMethodTest {
             .ids(ImmutableList.of(message.getMessageId()))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
             .extracting(JmapResponse::getResponse)
@@ -384,7 +384,7 @@ public class GetMessagesMethodTest {
             .ids(ImmutableList.of(message.getMessageId()))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
             .extracting(JmapResponse::getResponse)
@@ -418,7 +418,7 @@ public class GetMessagesMethodTest {
 
         Set<MessageProperty> expected = Sets.newHashSet(MessageProperty.id, MessageProperty.headers);
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1);
         assertThat(result.get(0).getProperties())
@@ -444,7 +444,7 @@ public class GetMessagesMethodTest {
             .properties(ImmutableList.of("headers.from", "headers.heADER2"))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result)
             .hasSize(1)
@@ -481,7 +481,7 @@ public class GetMessagesMethodTest {
             .properties(ImmutableList.of("mailboxIds"))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1);
         Method.Response response = result.get(0).getResponse();
@@ -518,7 +518,7 @@ public class GetMessagesMethodTest {
             .properties(ImmutableList.of("mailboxIds"))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1);
         Method.Response response = result.get(0).getResponse();
@@ -553,7 +553,7 @@ public class GetMessagesMethodTest {
             .properties(ImmutableList.of("mailboxIds", "textBody"))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1);
         Method.Response response = result.get(0).getResponse();
@@ -588,7 +588,7 @@ public class GetMessagesMethodTest {
             .properties(ImmutableList.of("mailboxIds", "to"))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1);
         Method.Response response = result.get(0).getResponse();
@@ -624,7 +624,7 @@ public class GetMessagesMethodTest {
             .properties(ImmutableList.of("mailboxIds"))
             .build();
 
-        List<JmapResponse> responses = testee.process(request, methodCallId, session).collect(Guavate.toImmutableList());
+        List<JmapResponse> responses = testee.processToStream(request, methodCallId, session).collect(Guavate.toImmutableList());
 
         assertThat(responses).hasSize(1);
         Method.Response response = responses.get(0).getResponse();
@@ -661,7 +661,7 @@ public class GetMessagesMethodTest {
                 message3.getMessageId()))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
             .extracting(JmapResponse::getResponse)
@@ -720,7 +720,7 @@ public class GetMessagesMethodTest {
                 message3.getMessageId()))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
             .extracting(JmapResponse::getResponse)
@@ -762,7 +762,7 @@ public class GetMessagesMethodTest {
             .ids(ImmutableList.of(message1.getMessageId()))
             .build();
 
-        List<JmapResponse> result = testee.process(request, methodCallId, session).collect(Collectors.toList());
+        List<JmapResponse> result = testee.processToStream(request, methodCallId, session).collect(Collectors.toList());
 
         assertThat(result).hasSize(1)
             .extracting(JmapResponse::getResponse)
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethodTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethodTest.java
index 9b41160..242bc8c 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethodTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethodTest.java
@@ -105,7 +105,7 @@ public class GetVacationResponseMethodTest {
 
         GetVacationRequest getVacationRequest = GetVacationRequest.builder().build();
 
-        Stream<JmapResponse> result = testee.process(getVacationRequest, methodCallId, mailboxSession);
+        Stream<JmapResponse> result = testee.processToStream(getVacationRequest, methodCallId, mailboxSession);
 
         JmapResponse expected = JmapResponse.builder()
             .methodCallId(methodCallId)
@@ -137,7 +137,7 @@ public class GetVacationResponseMethodTest {
 
         GetVacationRequest getVacationRequest = GetVacationRequest.builder().build();
 
-        Stream<JmapResponse> result = testee.process(getVacationRequest, methodCallId, mailboxSession);
+        Stream<JmapResponse> result = testee.processToStream(getVacationRequest, methodCallId, mailboxSession);
 
         JmapResponse expected = JmapResponse.builder()
             .methodCallId(methodCallId)
@@ -171,7 +171,7 @@ public class GetVacationResponseMethodTest {
 
         GetVacationRequest getVacationRequest = GetVacationRequest.builder().build();
 
-        Stream<JmapResponse> result = testee.process(getVacationRequest, methodCallId, mailboxSession);
+        Stream<JmapResponse> result = testee.processToStream(getVacationRequest, methodCallId, mailboxSession);
 
         JmapResponse expected = JmapResponse.builder()
             .methodCallId(methodCallId)
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/JmapResponseWriterImplTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/JmapResponseWriterImplTest.java
index 6c496ed..67469eb 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/JmapResponseWriterImplTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/JmapResponseWriterImplTest.java
@@ -28,10 +28,10 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import org.apache.james.jmap.draft.json.ObjectMapperFactory;
-import org.apache.james.jmap.draft.model.MethodCallId;
-import org.apache.james.jmap.draft.model.Property;
 import org.apache.james.jmap.draft.model.InvocationRequest;
 import org.apache.james.jmap.draft.model.InvocationResponse;
+import org.apache.james.jmap.draft.model.MethodCallId;
+import org.apache.james.jmap.draft.model.Property;
 import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.inmemory.InMemoryMessageId;
 import org.junit.Before;
@@ -46,6 +46,8 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 
+import reactor.core.publisher.Flux;
+
 public class JmapResponseWriterImplTest {
     private JmapResponseWriterImpl testee;
 
@@ -61,16 +63,17 @@ public class JmapResponseWriterImplTest {
         String expectedMethodCallId = "#1";
         String expectedId = "myId";
 
-        Stream<InvocationResponse> response = testee.formatMethodResponse(Stream.of(JmapResponse
-                .builder()
-                .methodCallId(MethodCallId.of(expectedMethodCallId))
-                .response(null)
-                .build()));
+        Stream<InvocationResponse> response = testee.formatMethodResponse(Flux.just(JmapResponse
+            .builder()
+            .methodCallId(MethodCallId.of(expectedMethodCallId))
+            .response(null)
+            .build()))
+            .toStream();
 
         List<InvocationResponse> responseList = response.collect(Collectors.toList());
         assertThat(responseList).hasSize(1)
-                .extracting(InvocationResponse::getResponseName, x -> x.getResults().get("id").asText(), InvocationResponse::getMethodCallId)
-                .containsExactly(tuple(expectedMethod, expectedId, expectedMethodCallId));
+            .extracting(InvocationResponse::getResponseName, x -> x.getResults().get("id").asText(), InvocationResponse::getMethodCallId)
+            .containsExactly(tuple(expectedMethod, expectedId, expectedMethodCallId));
     }
 
     @Test
@@ -82,24 +85,25 @@ public class JmapResponseWriterImplTest {
         responseClass.id = expectedId;
 
         List<InvocationResponse> response = testee.formatMethodResponse(
-                Stream.of(JmapResponse
+            Flux.just(JmapResponse
                 .builder()
                 .responseName(Method.Response.name("unknownMethod"))
                 .methodCallId(MethodCallId.of(expectedMethodCallId))
                 .response(responseClass)
                 .build()))
-                .collect(Collectors.toList());
+            .collectList()
+            .block();
 
         assertThat(response).hasSize(1)
-                .extracting(InvocationResponse::getResponseName, x -> x.getResults().get("id").asText(), InvocationResponse::getMethodCallId)
-                .containsExactly(tuple(Method.Response.name("unknownMethod"), expectedId, MethodCallId.of(expectedMethodCallId)));
+            .extracting(InvocationResponse::getResponseName, x -> x.getResults().get("id").asText(), InvocationResponse::getMethodCallId)
+            .containsExactly(tuple(Method.Response.name("unknownMethod"), expectedId, MethodCallId.of(expectedMethodCallId)));
     }
 
     private static class ResponseClass implements Method.Response {
 
         @SuppressWarnings("unused")
         public String id;
-        
+
     }
 
     @Test
@@ -109,14 +113,15 @@ public class JmapResponseWriterImplTest {
         Property property = () -> "id";
 
         List<InvocationResponse> response = testee.formatMethodResponse(
-                Stream.of(JmapResponse
+            Flux.just(JmapResponse
                 .builder()
                 .responseName(Method.Response.name("unknownMethod"))
                 .methodCallId(MethodCallId.of("#1"))
                 .properties(ImmutableSet.of(property))
                 .response(responseClass)
                 .build()))
-                .collect(Collectors.toList());
+            .collectList()
+            .block();
 
         assertThat(response).hasSize(1);
         JsonNode firstObject = Iterables.getOnlyElement(response).getResults().get("list").elements().next();
@@ -125,7 +130,6 @@ public class JmapResponseWriterImplTest {
     }
 
 
-
     @Test
     public void formatMethodResponseShouldNotFilterFieldsWhenSecondCallWithoutProperties() {
         ObjectResponseClass responseClass = new ObjectResponseClass();
@@ -134,22 +138,24 @@ public class JmapResponseWriterImplTest {
 
         @SuppressWarnings("unused")
         Stream<InvocationResponse> ignoredResponse = testee.formatMethodResponse(
-                Stream.of(JmapResponse
-                        .builder()
-                        .responseName(Method.Response.name("unknownMethod"))
-                        .methodCallId(MethodCallId.of("#1"))
-                        .properties(ImmutableSet.of(property))
-                        .response(responseClass)
-                        .build()));
+            Flux.just(JmapResponse
+                .builder()
+                .responseName(Method.Response.name("unknownMethod"))
+                .methodCallId(MethodCallId.of("#1"))
+                .properties(ImmutableSet.of(property))
+                .response(responseClass)
+                .build()))
+            .toStream();
 
         List<InvocationResponse> response = testee.formatMethodResponse(
-                Stream.of(JmapResponse
+            Flux.just(JmapResponse
                 .builder()
                 .responseName(Method.Response.name("unknownMethod"))
                 .methodCallId(MethodCallId.of("#1"))
                 .response(responseClass)
                 .build()))
-                .collect(Collectors.toList());
+            .collect(Collectors.toList())
+            .block();
 
         assertThat(response).hasSize(1);
         JsonNode firstObject = Iterables.getOnlyElement(response).getResults().get("list").elements().next();
@@ -166,28 +172,29 @@ public class JmapResponseWriterImplTest {
         Property nameProperty = () -> "name";
 
         List<InvocationResponse> response = testee.formatMethodResponse(
-                Stream.of(JmapResponse
-                            .builder()
-                            .responseName(Method.Response.name("unknownMethod"))
-                            .methodCallId(MethodCallId.of("#1"))
-                            .properties(ImmutableSet.of(idProperty, nameProperty))
-                            .response(responseClass)
-                            .build(),
-                        JmapResponse
-                            .builder()
-                            .responseName(Method.Response.name("unknownMethod"))
-                            .methodCallId(MethodCallId.of("#1"))
-                            .properties(ImmutableSet.of(idProperty))
-                            .response(responseClass)
-                            .build()))
-                .collect(Collectors.toList());
+            Flux.just(JmapResponse
+                    .builder()
+                    .responseName(Method.Response.name("unknownMethod"))
+                    .methodCallId(MethodCallId.of("#1"))
+                    .properties(ImmutableSet.of(idProperty, nameProperty))
+                    .response(responseClass)
+                    .build(),
+                JmapResponse
+                    .builder()
+                    .responseName(Method.Response.name("unknownMethod"))
+                    .methodCallId(MethodCallId.of("#1"))
+                    .properties(ImmutableSet.of(idProperty))
+                    .response(responseClass)
+                    .build()))
+            .collectList()
+            .block();
 
         assertThat(response).hasSize(2)
-                .extracting(x -> x.getResults().get("list").elements().next())
-                .extracting(
-                        x -> x.get("id").asText(),
-                        x -> Optional.ofNullable(x.get("name")).map(JsonNode::asText).orElse(null))
-                .containsExactly(tuple("id", "name"), tuple("id", null));
+            .extracting(x -> x.getResults().get("list").elements().next())
+            .extracting(
+                x -> x.get("id").asText(),
+                x -> Optional.ofNullable(x.get("name")).map(JsonNode::asText).orElse(null))
+            .containsExactly(tuple("id", "name"), tuple("id", null));
     }
 
     @SuppressWarnings("unused")
@@ -196,13 +203,13 @@ public class JmapResponseWriterImplTest {
         private static class Foo {
             public String id;
             public String name;
-            
+
             public Foo(String id, String name) {
                 this.id = id;
                 this.name = name;
             }
         }
-        
+
         public List<Foo> list;
     }
 
@@ -212,21 +219,22 @@ public class JmapResponseWriterImplTest {
 
         ObjectNode parameters = new ObjectNode(new JsonNodeFactory(false));
         parameters.put("id", "myId");
-        JsonNode[] nodes = new JsonNode[] { new ObjectNode(new JsonNodeFactory(false)).textNode("unknwonMethod"),
-                parameters,
-                new ObjectNode(new JsonNodeFactory(false)).textNode(expectedMethodCallId)};
+        JsonNode[] nodes = new JsonNode[]{new ObjectNode(new JsonNodeFactory(false)).textNode("unknwonMethod"),
+            parameters,
+            new ObjectNode(new JsonNodeFactory(false)).textNode(expectedMethodCallId)};
 
         List<InvocationResponse> response = testee.formatMethodResponse(
-                Stream.of(JmapResponse
-                    .builder()
-                    .methodCallId(InvocationRequest.deserialize(nodes).getMethodCallId())
-                    .error()
-                    .build()))
-                .collect(Collectors.toList());
+            Flux.just(JmapResponse
+                .builder()
+                .methodCallId(InvocationRequest.deserialize(nodes).getMethodCallId())
+                .error()
+                .build()))
+            .collectList()
+            .block();
 
         assertThat(response).hasSize(1)
-                .extracting(InvocationResponse::getResponseName, x -> x.getResults().get("type").asText(), InvocationResponse::getMethodCallId)
-                .containsExactly(tuple(ErrorResponse.ERROR_METHOD, ErrorResponse.DEFAULT_ERROR_MESSAGE, MethodCallId.of(expectedMethodCallId)));
+            .extracting(InvocationResponse::getResponseName, x -> x.getResults().get("type").asText(), InvocationResponse::getMethodCallId)
+            .containsExactly(tuple(ErrorResponse.ERROR_METHOD, ErrorResponse.DEFAULT_ERROR_MESSAGE, MethodCallId.of(expectedMethodCallId)));
     }
 
     @Test
@@ -235,25 +243,26 @@ public class JmapResponseWriterImplTest {
 
         ObjectNode parameters = new ObjectNode(new JsonNodeFactory(false));
         parameters.put("id", "myId");
-        JsonNode[] nodes = new JsonNode[] { new ObjectNode(new JsonNodeFactory(false)).textNode("unknwonMethod"),
-                parameters,
-                new ObjectNode(new JsonNodeFactory(false)).textNode(expectedMethodCallId)};
+        JsonNode[] nodes = new JsonNode[]{new ObjectNode(new JsonNodeFactory(false)).textNode("unknwonMethod"),
+            parameters,
+            new ObjectNode(new JsonNodeFactory(false)).textNode(expectedMethodCallId)};
 
         List<InvocationResponse> response = testee.formatMethodResponse(
-                Stream.of(JmapResponse
+            Flux.just(JmapResponse
+                .builder()
+                .methodCallId(InvocationRequest.deserialize(nodes).getMethodCallId())
+                .error(ErrorResponse
                     .builder()
-                    .methodCallId(InvocationRequest.deserialize(nodes).getMethodCallId())
-                    .error(ErrorResponse
-                            .builder()
-                            .type("errorType")
-                            .description("complete description")
-                            .build())
-                    .build()))
-                .collect(Collectors.toList());
+                    .type("errorType")
+                    .description("complete description")
+                    .build())
+                .build()))
+            .collectList()
+            .block();
 
         assertThat(response).hasSize(1)
-                .extracting(InvocationResponse::getResponseName, x -> x.getResults().get("type").asText(), x -> x.getResults().get("description").asText(), InvocationResponse::getMethodCallId)
-                .containsExactly(tuple(ErrorResponse.ERROR_METHOD, "errorType", "complete description", MethodCallId.of(expectedMethodCallId)));
+            .extracting(InvocationResponse::getResponseName, x -> x.getResults().get("type").asText(), x -> x.getResults().get("description").asText(), InvocationResponse::getMethodCallId)
+            .containsExactly(tuple(ErrorResponse.ERROR_METHOD, "errorType", "complete description", MethodCallId.of(expectedMethodCallId)));
     }
 
 }
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/RequestHandlerTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/RequestHandlerTest.java
index 0eed4d8..2934f62 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/RequestHandlerTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/RequestHandlerTest.java
@@ -106,7 +106,7 @@ public class RequestHandlerTest {
         }
 
         @Override
-        public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+        public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
             Preconditions.checkArgument(request instanceof TestJmapRequest);
             TestJmapRequest typedRequest = (TestJmapRequest) request;
             return Stream.of(
@@ -193,7 +193,7 @@ public class RequestHandlerTest {
         }
         
         @Override
-        public Stream<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+        public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
             return null;
         }
     }
@@ -209,7 +209,8 @@ public class RequestHandlerTest {
                 new ObjectNode(new JsonNodeFactory(false)).textNode("#1")};
 
         List<InvocationResponse> responses = testee.handle(AuthenticatedRequest.decorate(InvocationRequest.deserialize(nodes), session))
-                .collect(Collectors.toList());
+                .collectList()
+                .block();
 
         assertThat(responses).hasSize(1)
                 .extracting(
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesMethodTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesMethodTest.java
index 1ba5182..cb8be95 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesMethodTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesMethodTest.java
@@ -61,7 +61,7 @@ public class SetMailboxesMethodTest {
     public void processShouldThrowWhenNullJmapRequest() {
         MailboxSession session = mock(MailboxSession.class);
         JmapRequest nullJmapRequest = null;
-        assertThatThrownBy(() -> new SetMailboxesMethod(NO_PROCESSOR, TIME_METRIC_FACTORY).process(nullJmapRequest, MethodCallId.of("methodCallId"), session))
+        assertThatThrownBy(() -> new SetMailboxesMethod(NO_PROCESSOR, TIME_METRIC_FACTORY).processToStream(nullJmapRequest, MethodCallId.of("methodCallId"), session))
             .isInstanceOf(NullPointerException.class);
     }
 
@@ -70,7 +70,7 @@ public class SetMailboxesMethodTest {
         MailboxSession session = mock(MailboxSession.class);
         JmapRequest jmapRequest = mock(JmapRequest.class);
         MethodCallId nullMethodCallId = null;
-        assertThatThrownBy(() -> new SetMailboxesMethod(NO_PROCESSOR, TIME_METRIC_FACTORY).process(jmapRequest, nullMethodCallId, session))
+        assertThatThrownBy(() -> new SetMailboxesMethod(NO_PROCESSOR, TIME_METRIC_FACTORY).processToStream(jmapRequest, nullMethodCallId, session))
             .isInstanceOf(NullPointerException.class);
     }
 
@@ -78,7 +78,7 @@ public class SetMailboxesMethodTest {
     public void processShouldThrowWhenNullMailboxSession() {
         MailboxSession nullMailboxSession = null;
         JmapRequest jmapRequest = mock(JmapRequest.class);
-        assertThatThrownBy(() -> new SetMailboxesMethod(NO_PROCESSOR, TIME_METRIC_FACTORY).process(jmapRequest, MethodCallId.of("methodCallId"), nullMailboxSession))
+        assertThatThrownBy(() -> new SetMailboxesMethod(NO_PROCESSOR, TIME_METRIC_FACTORY).processToStream(jmapRequest, MethodCallId.of("methodCallId"), nullMailboxSession))
             .isInstanceOf(NullPointerException.class);
     }
 
@@ -86,7 +86,7 @@ public class SetMailboxesMethodTest {
     public void processShouldThrowWhenJmapRequestTypeMismatch() {
         MailboxSession session = mock(MailboxSession.class);
         JmapRequest getMailboxesRequest = GetMailboxesRequest.builder().build();
-        assertThatThrownBy(() -> new SetMailboxesMethod(NO_PROCESSOR, TIME_METRIC_FACTORY).process(getMailboxesRequest, MethodCallId.of("methodCallId"), session))
+        assertThatThrownBy(() -> new SetMailboxesMethod(NO_PROCESSOR, TIME_METRIC_FACTORY).processToStream(getMailboxesRequest, MethodCallId.of("methodCallId"), session))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
@@ -110,7 +110,7 @@ public class SetMailboxesMethodTest {
 
         Stream<JmapResponse> actual =
             new SetMailboxesMethod(ImmutableSet.of(creatorProcessor), TIME_METRIC_FACTORY)
-                    .process(creationRequest, MethodCallId.of("methodCallId"), session);
+                    .processToStream(creationRequest, MethodCallId.of("methodCallId"), session);
 
         assertThat(actual).contains(jmapResponse);
     }
@@ -133,7 +133,7 @@ public class SetMailboxesMethodTest {
 
         Stream<JmapResponse> actual =
             new SetMailboxesMethod(ImmutableSet.of(destructorProcessor), TIME_METRIC_FACTORY)
-                    .process(destructionRequest, MethodCallId.of("methodCallId"), session);
+                    .processToStream(destructionRequest, MethodCallId.of("methodCallId"), session);
 
         assertThat(actual).contains(jmapResponse);
     }
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethodTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethodTest.java
index c45f3f4..50695c3 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethodTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethodTest.java
@@ -73,22 +73,22 @@ public class SetVacationResponseMethodTest {
 
     @Test(expected = NullPointerException.class)
     public void processShouldThrowOnNullRequest() {
-        testee.process(null, mock(MethodCallId.class), mock(MailboxSession.class));
+        testee.processToStream(null, mock(MethodCallId.class), mock(MailboxSession.class));
     }
 
     @Test(expected = NullPointerException.class)
     public void processShouldThrowOnNullMethodCallId() {
-        testee.process(mock(SetMailboxesRequest.class), null, mock(MailboxSession.class));
+        testee.processToStream(mock(SetMailboxesRequest.class), null, mock(MailboxSession.class));
     }
 
     @Test(expected = NullPointerException.class)
     public void processShouldThrowOnNullMailboxSession() {
-        testee.process(mock(SetMailboxesRequest.class), mock(MethodCallId.class), null);
+        testee.processToStream(mock(SetMailboxesRequest.class), mock(MethodCallId.class), null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void processShouldThrowOnWrongRequestType() {
-        testee.process(mock(GetMailboxesRequest.class), mock(MethodCallId.class), mock(MailboxSession.class));
+        testee.processToStream(mock(GetMailboxesRequest.class), mock(MethodCallId.class), mock(MailboxSession.class));
     }
 
     @Test
@@ -97,7 +97,7 @@ public class SetVacationResponseMethodTest {
             .update(ImmutableMap.of())
             .build();
 
-        Stream<JmapResponse> result = testee.process(setVacationRequest, methodCallId, mock(MailboxSession.class));
+        Stream<JmapResponse> result = testee.processToStream(setVacationRequest, methodCallId, mock(MailboxSession.class));
 
         JmapResponse expected = JmapResponse.builder()
             .methodCallId(methodCallId)
@@ -120,7 +120,7 @@ public class SetVacationResponseMethodTest {
                 .build()))
             .build();
 
-        Stream<JmapResponse> result = testee.process(setVacationRequest, methodCallId, mock(MailboxSession.class));
+        Stream<JmapResponse> result = testee.processToStream(setVacationRequest, methodCallId, mock(MailboxSession.class));
 
         JmapResponse expected = JmapResponse.builder()
             .methodCallId(methodCallId)
@@ -148,7 +148,7 @@ public class SetVacationResponseMethodTest {
                     .build()))
             .build();
 
-        Stream<JmapResponse> result = testee.process(setVacationRequest, methodCallId, mock(MailboxSession.class));
+        Stream<JmapResponse> result = testee.processToStream(setVacationRequest, methodCallId, mock(MailboxSession.class));
 
         JmapResponse expected = JmapResponse.builder()
             .methodCallId(methodCallId)
@@ -178,7 +178,7 @@ public class SetVacationResponseMethodTest {
         when(notificationRegistry.flush(any()))
             .thenReturn(Mono.empty());
 
-        Stream<JmapResponse> result = testee.process(setVacationRequest, methodCallId, mailboxSession);
+        Stream<JmapResponse> result = testee.processToStream(setVacationRequest, methodCallId, mailboxSession);
 
         JmapResponse expected = JmapResponse.builder()
             .methodCallId(methodCallId)
@@ -205,7 +205,7 @@ public class SetVacationResponseMethodTest {
             .build();
         when(mailboxSession.getUser()).thenReturn(USERNAME);
 
-        Stream<JmapResponse> result = testee.process(setVacationRequest, methodCallId, mailboxSession);
+        Stream<JmapResponse> result = testee.processToStream(setVacationRequest, methodCallId, mailboxSession);
 
         JmapResponse expected = JmapResponse.builder()
             .methodCallId(methodCallId)
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JMAPApiRoutesTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JMAPApiRoutesTest.java
index 2a31456..e8cafca 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JMAPApiRoutesTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JMAPApiRoutesTest.java
@@ -48,6 +48,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
 import io.restassured.RestAssured;
 import io.restassured.builder.RequestSpecBuilder;
 import io.restassured.http.ContentType;
+import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 import reactor.netty.DisposableServer;
 import reactor.netty.http.server.HttpServer;
@@ -115,7 +116,7 @@ public class JMAPApiRoutesTest {
         json.put("type", "invalidArgument");
 
         when(requestHandler.handle(any()))
-            .thenReturn(Stream.of(new InvocationResponse(ErrorResponse.ERROR_METHOD, json, MethodCallId.of("#0"))));
+            .thenReturn(Flux.just(new InvocationResponse(ErrorResponse.ERROR_METHOD, json, MethodCallId.of("#0"))));
 
         given()
             .body("[[\"getAccounts\", {\"state\":false}, \"#0\"]]")
@@ -137,7 +138,7 @@ public class JMAPApiRoutesTest {
         arrayNode.add(list);
 
         when(requestHandler.handle(any()))
-            .thenReturn(Stream.of(new InvocationResponse(Method.Response.name("accounts"), json, MethodCallId.of("#0"))));
+            .thenReturn(Flux.just(new InvocationResponse(Method.Response.name("accounts"), json, MethodCallId.of("#0"))));
 
         given()
             .body("[[\"getAccounts\", {}, \"#0\"]]")


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


[james-project] 05/15: JAMES-2632 Add a MailboxPath::child method

Posted by bt...@apache.org.
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 948252e3e0c6b3f5be8b72eaab93b15ed763883e
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Mar 30 15:42:52 2020 +0700

    JAMES-2632 Add a MailboxPath::child method
---
 .../apache/james/mailbox/model/MailboxPath.java    |  9 +++++++
 .../james/mailbox/model/MailboxPathTest.java       | 28 ++++++++++++++++++++++
 .../james/jmap/draft/model/MailboxFactoryTest.java |  4 ++--
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxPath.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxPath.java
index f2617b7..3c6a8ed 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxPath.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxPath.java
@@ -32,6 +32,8 @@ import org.apache.james.mailbox.exception.MailboxNameException;
 import org.apache.james.mailbox.exception.TooLongMailboxNameException;
 
 import com.google.common.base.CharMatcher;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 
 /**
@@ -108,6 +110,13 @@ public class MailboxPath {
         return user.equals(mailboxSession.getUser());
     }
 
+    public MailboxPath child(String childName, char delimiter) {
+        Preconditions.checkArgument(!Strings.isNullOrEmpty(childName), "'childName' should not be null or empty");
+        Preconditions.checkArgument(!childName.contains(String.valueOf(delimiter)), "'childName' should not contain delimiter");
+
+        return new MailboxPath(namespace, user, name + delimiter + childName);
+    }
+
     /**
      * Return a list of MailboxPath representing the hierarchy levels of this
      * MailboxPath. E.g. INBOX.main.sub would yield
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxPathTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxPathTest.java
index 453c91f..f421ed7 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxPathTest.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxPathTest.java
@@ -61,6 +61,34 @@ class MailboxPathTest {
     }
 
     @Test
+    void childShouldConcatenateChildNameWithParentForlder() {
+        assertThat(MailboxPath.forUser(USER, "folder")
+            .child("toto", '.'))
+            .isEqualTo(MailboxPath.forUser(USER, "folder.toto"));
+    }
+
+    @Test
+    void childShouldThrowWhenNull() {
+        MailboxPath path = MailboxPath.forUser(USER, "folder");
+        assertThatThrownBy(() -> path.child(null, '.'))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void childShouldThrowWhenEmpty() {
+        MailboxPath path = MailboxPath.forUser(USER, "folder");
+        assertThatThrownBy(() -> path.child("", '.'))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    void childShouldThrowWhenContainsDelimiter() {
+        MailboxPath path = MailboxPath.forUser(USER, "folder");
+        assertThatThrownBy(() -> path.child("a.b", '.'))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
     void getHierarchyLevelsShouldReturnPathWhenOneLevel() {
         assertThat(MailboxPath.forUser(USER, "inbox")
             .getHierarchyLevels('.'))
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 14d9d42..f235996 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
@@ -144,7 +144,7 @@ public class MailboxFactoryTest {
         mailboxManager.createMailbox(parentMailboxPath, mailboxSession);
         MailboxId parentId = mailboxManager.getMailbox(parentMailboxPath, mailboxSession).getId();
 
-        MailboxPath mailboxPath = MailboxPath.forUser(user, "INBOX.mailbox");
+        MailboxPath mailboxPath = parentMailboxPath.child("mailbox", '.');
         mailboxManager.createMailbox(mailboxPath, mailboxSession);
 
         Optional<MailboxId> id = sut.getParentIdFromMailboxPath(mailboxPath, Optional.empty(), mailboxSession);
@@ -202,7 +202,7 @@ public class MailboxFactoryTest {
     public void buildShouldRelyOnPreloadedMailboxes() throws Exception {
         MailboxPath inbox = MailboxPath.inbox(user);
         Optional<MailboxId> inboxId = mailboxManager.createMailbox(inbox, mailboxSession);
-        Optional<MailboxId> otherId = mailboxManager.createMailbox(MailboxPath.forUser(user, "INBOX.child"), mailboxSession);
+        Optional<MailboxId> otherId = mailboxManager.createMailbox(inbox.child("child", '.'), mailboxSession);
 
         InMemoryId preLoadedId = InMemoryId.of(45);
         Mailbox retrievedMailbox = sut.builder()


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


[james-project] 02/15: [Performance] Avoid loading mailbox counters for getAllReadableMailboxes

Posted by bt...@apache.org.
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 ed3b695b0abd28c82ea37fe7de59aaa2cd6be74a
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Mar 30 14:20:53 2020 +0700

    [Performance] Avoid loading mailbox counters for getAllReadableMailboxes
    
    Glowroot flameGraph suggest we spend 60% of GetMessageList time loading
    mailbox counters while we do not need them
---
 .../james/mailbox/store/StoreMailboxManager.java   | 28 ++++++++++++----------
 .../vault/DeletedMessageVaultIntegrationTest.java  |  4 ++--
 .../org/apache/james/jmap/JmapCommonRequests.java  |  4 ++--
 3 files changed, 20 insertions(+), 16 deletions(-)

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 6cb08a8..c2da6e9 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
@@ -592,19 +592,11 @@ public class StoreMailboxManager implements MailboxManager {
 
     @Override
     public List<MailboxMetaData> search(MailboxQuery mailboxExpression, MailboxSession session) throws MailboxException {
-        return searchMailboxes(mailboxExpression, session, Right.Lookup);
+        return searchMailboxesMetadata(mailboxExpression, session, Right.Lookup);
     }
 
-    private List<MailboxMetaData> searchMailboxes(MailboxQuery mailboxQuery, MailboxSession session, Right right) throws MailboxException {
-        MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(session);
-        Stream<Mailbox> baseMailboxes = mailboxMapper
-            .findMailboxWithPathLike(toSingleUserQuery(mailboxQuery, session))
-            .stream();
-        Stream<Mailbox> delegatedMailboxes = getDelegatedMailboxes(mailboxMapper, mailboxQuery, right, session);
-        List<Mailbox> mailboxes = Stream.concat(baseMailboxes, delegatedMailboxes)
-            .distinct()
-            .filter(Throwing.predicate(mailbox -> storeRightManager.hasRight(mailbox, right, session)))
-            .collect(Guavate.toImmutableList());
+    private List<MailboxMetaData> searchMailboxesMetadata(MailboxQuery mailboxQuery, MailboxSession session, Right right) throws MailboxException {
+        List<Mailbox> mailboxes = searchMailboxes(mailboxQuery, session, right);
 
         ImmutableMap<MailboxId, MailboxCounters> counters = getMailboxCounters(mailboxes, session)
             .stream()
@@ -622,6 +614,18 @@ public class StoreMailboxManager implements MailboxManager {
             .collect(Guavate.toImmutableList());
     }
 
+    private List<Mailbox> searchMailboxes(MailboxQuery mailboxQuery, MailboxSession session, Right right) throws MailboxException {
+        MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(session);
+        Stream<Mailbox> baseMailboxes = mailboxMapper
+            .findMailboxWithPathLike(toSingleUserQuery(mailboxQuery, session))
+            .stream();
+        Stream<Mailbox> delegatedMailboxes = getDelegatedMailboxes(mailboxMapper, mailboxQuery, right, session);
+        return Stream.concat(baseMailboxes, delegatedMailboxes)
+            .distinct()
+            .filter(Throwing.predicate(mailbox -> storeRightManager.hasRight(mailbox, right, session)))
+            .collect(Guavate.toImmutableList());
+    }
+
     static MailboxQuery.UserBound toSingleUserQuery(MailboxQuery mailboxQuery, MailboxSession mailboxSession) {
         return MailboxQuery.builder()
             .namespace(mailboxQuery.getNamespace().orElse(MailboxConstants.USER_NAMESPACE))
@@ -693,7 +697,7 @@ public class StoreMailboxManager implements MailboxManager {
     private Stream<MailboxId> getAllReadableMailbox(MailboxSession session) throws MailboxException {
         return searchMailboxes(MailboxQuery.builder().matchesAllMailboxNames().build(), session, Right.Read)
             .stream()
-            .map(MailboxMetaData::getId);
+            .map(Mailbox::getMailboxId);
     }
 
     @Override
diff --git a/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/DeletedMessageVaultIntegrationTest.java b/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/DeletedMessageVaultIntegrationTest.java
index f166582..ae04e91 100644
--- a/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/DeletedMessageVaultIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/DeletedMessageVaultIntegrationTest.java
@@ -30,7 +30,7 @@ import static org.apache.james.jmap.JMAPTestingConstants.calmlyAwait;
 import static org.apache.james.jmap.JMAPTestingConstants.jmapRequestSpecBuilder;
 import static org.apache.james.jmap.JmapCommonRequests.deleteMessages;
 import static org.apache.james.jmap.JmapCommonRequests.getAllMailboxesIds;
-import static org.apache.james.jmap.JmapCommonRequests.getLastMessageId;
+import static org.apache.james.jmap.JmapCommonRequests.getLatestMessageId;
 import static org.apache.james.jmap.JmapCommonRequests.getOutboxId;
 import static org.apache.james.jmap.JmapCommonRequests.listMessageIdsForAccount;
 import static org.apache.james.jmap.LocalHostURIBuilder.baseUri;
@@ -823,7 +823,7 @@ public abstract class DeletedMessageVaultIntegrationTest {
         exportVaultContent(webAdminApi, exportRequest);
 
         WAIT_TWO_MINUTES.until(() -> listMessageIdsForAccount(shareeAccessToken).size() == currentNumberOfMessages + 1);
-        String exportingMessageId = getLastMessageId(shareeAccessToken);
+        String exportingMessageId = getLatestMessageId(shareeAccessToken, Role.INBOX);
 
         return exportedFileLocationFromMailHeader(exportingMessageId, shareeAccessToken);
     }
diff --git a/server/testing/src/main/java/org/apache/james/jmap/JmapCommonRequests.java b/server/testing/src/main/java/org/apache/james/jmap/JmapCommonRequests.java
index 72138fe..981e549 100644
--- a/server/testing/src/main/java/org/apache/james/jmap/JmapCommonRequests.java
+++ b/server/testing/src/main/java/org/apache/james/jmap/JmapCommonRequests.java
@@ -141,10 +141,10 @@ public class JmapCommonRequests {
     }
 
     public static String getLatestMessageId(AccessToken accessToken, Role mailbox) {
-        String inboxId = getMailboxId(accessToken, mailbox);
+        String mailboxId = getMailboxId(accessToken, mailbox);
         return with()
                 .header("Authorization", accessToken.asString())
-                .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + inboxId + "\"]}, \"sort\":[\"date desc\"]}, \"#0\"]]")
+                .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + mailboxId + "\"]}, \"sort\":[\"date desc\"]}, \"#0\"]]")
                 .post("/jmap")
             .then()
                 .extract()


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


[james-project] 01/15: [Build] Fasten JMAP Draft memory integration testing

Posted by bt...@apache.org.
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 cdc93045df905c261d59be213c05489142970b12
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Apr 1 09:36:14 2020 +0700

    [Build] Fasten JMAP Draft memory integration testing
---
 .../modules/mailbox/FastRetryBackoffModule.java    | 38 ++++++++++++++++++++++
 .../container/guice/protocols/jmap-draft/pom.xml   |  4 +++
 .../apache/james/modules/TestJMAPServerModule.java |  5 +++
 3 files changed, 47 insertions(+)

diff --git a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/FastRetryBackoffModule.java b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/FastRetryBackoffModule.java
new file mode 100644
index 0000000..a0cd52d
--- /dev/null
+++ b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/mailbox/FastRetryBackoffModule.java
@@ -0,0 +1,38 @@
+/****************************************************************
+ * 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.modules.mailbox;
+
+import java.time.Duration;
+
+import org.apache.james.mailbox.events.RetryBackoffConfiguration;
+
+import com.google.inject.AbstractModule;
+
+public class FastRetryBackoffModule extends AbstractModule {
+    @Override
+    protected void configure() {
+        bind(RetryBackoffConfiguration.class)
+            .toInstance(RetryBackoffConfiguration.builder()
+                .maxRetries(3)
+                .firstBackoff(Duration.ofMillis(10))
+                .jitterFactor(0.2)
+                .build());
+    }
+}
diff --git a/server/container/guice/protocols/jmap-draft/pom.xml b/server/container/guice/protocols/jmap-draft/pom.xml
index dc5156f..5979be9 100644
--- a/server/container/guice/protocols/jmap-draft/pom.xml
+++ b/server/container/guice/protocols/jmap-draft/pom.xml
@@ -55,6 +55,10 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-guice-mailbox</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-server-jmap-draft</artifactId>
         </dependency>
         <dependency>
diff --git a/server/container/guice/protocols/jmap-draft/src/test/java/org/apache/james/modules/TestJMAPServerModule.java b/server/container/guice/protocols/jmap-draft/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
index c455d1e..374d36a 100644
--- a/server/container/guice/protocols/jmap-draft/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
+++ b/server/container/guice/protocols/jmap-draft/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
@@ -20,6 +20,7 @@
 package org.apache.james.modules;
 
 import java.io.FileNotFoundException;
+import java.time.Duration;
 import java.util.Optional;
 
 import javax.inject.Singleton;
@@ -28,6 +29,8 @@ import org.apache.commons.configuration2.ex.ConfigurationException;
 import org.apache.james.jmap.JMAPConfiguration;
 import org.apache.james.jmap.draft.JMAPDraftConfiguration;
 import org.apache.james.jmap.draft.methods.GetMessageListMethod;
+import org.apache.james.mailbox.events.RetryBackoffConfiguration;
+import org.apache.james.modules.mailbox.FastRetryBackoffModule;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
@@ -106,6 +109,8 @@ public class TestJMAPServerModule extends AbstractModule {
 
     @Override
     protected void configure() {
+        install(new FastRetryBackoffModule());
+
         bindConstant().annotatedWith(Names.named(GetMessageListMethod.MAXIMUM_LIMIT)).to(maximumLimit);
     }
 


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


[james-project] 14/15: JAMES-3078 Reactify SetVacation

Posted by bt...@apache.org.
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 653525ce3d93fa88dfd7c8d6c35ecc0456679341
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sun Mar 22 18:12:04 2020 +0700

    JAMES-3078 Reactify SetVacation
---
 .../draft/methods/SetVacationResponseMethod.java   | 44 ++++++++++------------
 1 file changed, 19 insertions(+), 25 deletions(-)

diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
index 215223c..d8952b8 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
@@ -19,8 +19,6 @@
 
 package org.apache.james.jmap.draft.methods;
 
-import java.util.stream.Stream;
-
 import javax.inject.Inject;
 
 import org.apache.james.jmap.api.vacation.AccountId;
@@ -34,10 +32,12 @@ import org.apache.james.jmap.draft.model.SetVacationResponse;
 import org.apache.james.jmap.draft.model.VacationResponse;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.metrics.api.MetricFactory;
-import org.apache.james.util.MDCBuilder;
 
 import com.google.common.base.Preconditions;
 
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
 public class SetVacationResponseMethod implements Method {
 
     public static final Request.Name METHOD_NAME = Request.name("setVacationResponse");
@@ -69,26 +69,20 @@ public class SetVacationResponseMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Flux<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(methodCallId);
         Preconditions.checkNotNull(mailboxSession);
         Preconditions.checkArgument(request instanceof SetVacationRequest);
         SetVacationRequest setVacationRequest = (SetVacationRequest) request;
 
-
-        return MDCBuilder.create()
-            .addContext(MDCBuilder.ACTION, "SET_VACATION")
-            .addContext("update", setVacationRequest.getUpdate())
-            .wrapArround(
-                () -> metricFactory.runPublishingTimerMetricLogP99(JMAP_PREFIX + METHOD_NAME.getName(),
-                    () -> process(methodCallId, mailboxSession, setVacationRequest)))
-            .get();
+        return metricFactory.runPublishingTimerMetricLogP99(JMAP_PREFIX + METHOD_NAME.getName(),
+            () -> process(methodCallId, mailboxSession, setVacationRequest));
     }
 
-    private Stream<JmapResponse> process(MethodCallId methodCallId, MailboxSession mailboxSession, SetVacationRequest setVacationRequest) {
+    private Flux<JmapResponse> process(MethodCallId methodCallId, MailboxSession mailboxSession, SetVacationRequest setVacationRequest) {
         if (!setVacationRequest.isValid()) {
-            return Stream.of(JmapResponse
+            return Flux.just(JmapResponse
                 .builder()
                 .methodCallId(methodCallId)
                 .error(ErrorResponse.builder()
@@ -104,19 +98,19 @@ public class SetVacationResponseMethod implements Method {
     }
 
 
-    private Stream<JmapResponse> process(MethodCallId methodCallId, AccountId accountId, VacationResponse vacationResponse) {
+    private Flux<JmapResponse> process(MethodCallId methodCallId, AccountId accountId, VacationResponse vacationResponse) {
         if (vacationResponse.isValid()) {
-            vacationRepository.modifyVacation(accountId, vacationResponse.getPatch()).block();
-            notificationRegistry.flush(accountId).block();
-            return Stream.of(JmapResponse.builder()
-                .methodCallId(methodCallId)
-                .responseName(RESPONSE_NAME)
-                .response(SetVacationResponse.builder()
-                    .updatedId(Vacation.ID)
-                    .build())
-                .build());
+            return vacationRepository.modifyVacation(accountId, vacationResponse.getPatch())
+                .then(notificationRegistry.flush(accountId))
+                .thenMany(Mono.just(JmapResponse.builder()
+                    .methodCallId(methodCallId)
+                    .responseName(RESPONSE_NAME)
+                    .response(SetVacationResponse.builder()
+                        .updatedId(Vacation.ID)
+                        .build())
+                    .build()));
         } else {
-            return Stream.of(JmapResponse.builder()
+            return Flux.just(JmapResponse.builder()
                 .methodCallId(methodCallId)
                 .responseName(RESPONSE_NAME)
                 .response(SetVacationResponse.builder()


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


[james-project] 07/15: JAMES-2648 Rely on CassandraSchemaVersionManager for version computation

Posted by bt...@apache.org.
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 984dc0fb77da12cf8eb7cdab2c7790646b6de46e
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Mar 30 17:48:52 2020 +0700

    JAMES-2648 Rely on CassandraSchemaVersionManager for version computation
---
 .../rrt/cassandra/CassandraRecipientRewriteTable.java   | 17 +++++------------
 .../cassandra/CassandraRecipientRewriteTableV6Test.java |  9 ++++-----
 .../cassandra/CassandraRecipientRewriteTableV7Test.java |  9 ++++-----
 .../apache/james/rrt/cassandra/CassandraStepdefs.java   |  6 ++++--
 4 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
index d28e2e2..1997e53 100644
--- a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
@@ -23,7 +23,6 @@ import java.util.stream.Stream;
 
 import javax.inject.Inject;
 
-import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
 import org.apache.james.core.Domain;
@@ -43,18 +42,18 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
 
     private final CassandraRecipientRewriteTableDAO cassandraRecipientRewriteTableDAO;
     private final CassandraMappingsSourcesDAO cassandraMappingsSourcesDAO;
-    private final CassandraSchemaVersionDAO cassandraSchemaVersionDAO;
+    private final CassandraSchemaVersionManager versionManager;
     private final SchemaVersion initialSchemaVersion;
 
     @Inject
     CassandraRecipientRewriteTable(CassandraRecipientRewriteTableDAO cassandraRecipientRewriteTableDAO,
                                    CassandraMappingsSourcesDAO cassandraMappingsSourcesDAO,
-                                   CassandraSchemaVersionDAO cassandraSchemaVersionDAO) {
+                                   CassandraSchemaVersionManager versionManager) {
         this.cassandraRecipientRewriteTableDAO = cassandraRecipientRewriteTableDAO;
         this.cassandraMappingsSourcesDAO = cassandraMappingsSourcesDAO;
-        this.cassandraSchemaVersionDAO = cassandraSchemaVersionDAO;
+        this.versionManager = versionManager;
 
-        initialSchemaVersion = retrieveCurrentSchemaVersion();
+        initialSchemaVersion = versionManager.computeVersion();
     }
 
     @Override
@@ -111,16 +110,10 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
     private boolean isLegacy() {
         return isLegacy(initialSchemaVersion)
             // If we started with a legacy james then maybe schema version had been updated since then
-            || isLegacy(retrieveCurrentSchemaVersion());
+            || isLegacy(versionManager.computeVersion());
     }
 
     private boolean isLegacy(SchemaVersion schemaVersion) {
         return schemaVersion.isBefore(MAPPINGS_SOURCES_SUPPORTED_VERSION);
     }
-
-    private SchemaVersion retrieveCurrentSchemaVersion() {
-        return cassandraSchemaVersionDAO.getCurrentSchemaVersion()
-            .block()
-            .orElse(CassandraSchemaVersionManager.MIN_VERSION);
-    }
 }
diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV6Test.java b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV6Test.java
index 34e51ad..69aea33 100644
--- a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV6Test.java
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV6Test.java
@@ -19,12 +19,12 @@
 
 package org.apache.james.rrt.cassandra;
 
-import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
@@ -60,15 +60,14 @@ public class CassandraRecipientRewriteTableV6Test extends AbstractRecipientRewri
     }
 
     @Override
-    protected AbstractRecipientRewriteTable getRecipientRewriteTable() throws Exception {
+    protected AbstractRecipientRewriteTable getRecipientRewriteTable() {
         CassandraSchemaVersionDAO cassandraSchemaVersionDAO = new CassandraSchemaVersionDAO(
-            cassandra.getConf()
-        );
+            cassandra.getConf());
 
         CassandraRecipientRewriteTable rrt = new CassandraRecipientRewriteTable(
             new CassandraRecipientRewriteTableDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION),
             new CassandraMappingsSourcesDAO(cassandra.getConf()),
-            cassandraSchemaVersionDAO);
+            new CassandraSchemaVersionManager(cassandraSchemaVersionDAO));
 
         cassandraSchemaVersionDAO.updateVersion(SCHEMA_VERSION_V6);
 
diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java
index 2c6a205..063cb83 100644
--- a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java
@@ -19,12 +19,12 @@
 
 package org.apache.james.rrt.cassandra;
 
-import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
@@ -60,15 +60,14 @@ public class CassandraRecipientRewriteTableV7Test extends AbstractRecipientRewri
     }
 
     @Override
-    protected AbstractRecipientRewriteTable getRecipientRewriteTable() throws Exception {
+    protected AbstractRecipientRewriteTable getRecipientRewriteTable() {
         CassandraSchemaVersionDAO cassandraSchemaVersionDAO = new CassandraSchemaVersionDAO(
-            cassandra.getConf()
-        );
+            cassandra.getConf());
 
         CassandraRecipientRewriteTable rrt = new CassandraRecipientRewriteTable(
             new CassandraRecipientRewriteTableDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION),
             new CassandraMappingsSourcesDAO(cassandra.getConf()),
-            cassandraSchemaVersionDAO);
+            new CassandraSchemaVersionManager(cassandraSchemaVersionDAO));
 
         cassandraSchemaVersionDAO.updateVersion(SCHEMA_VERSION_V7);
 
diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraStepdefs.java b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraStepdefs.java
index eb16b46..6738118 100644
--- a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraStepdefs.java
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraStepdefs.java
@@ -23,6 +23,7 @@ import org.apache.james.backends.cassandra.DockerCassandraRule;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
 import org.apache.james.rrt.lib.RecipientRewriteTableFixture;
@@ -30,6 +31,7 @@ import org.apache.james.rrt.lib.RewriteTablesStepdefs;
 import org.junit.Rule;
 
 import com.github.fge.lambdas.Throwing;
+
 import cucumber.api.java.After;
 import cucumber.api.java.Before;
 
@@ -47,7 +49,7 @@ public class CassandraStepdefs {
     }
 
     @Before
-    public void setup() throws Throwable {
+    public void setup() {
         cassandra = CassandraCluster.create(
             CassandraModule.aggregateModules(CassandraRRTModule.MODULE, CassandraSchemaVersionModule.MODULE),
             cassandraServer.getHost());
@@ -63,7 +65,7 @@ public class CassandraStepdefs {
         CassandraRecipientRewriteTable rrt = new CassandraRecipientRewriteTable(
             new CassandraRecipientRewriteTableDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION),
             new CassandraMappingsSourcesDAO(cassandra.getConf()),
-            new CassandraSchemaVersionDAO(cassandra.getConf()));
+            new CassandraSchemaVersionManager(new CassandraSchemaVersionDAO(cassandra.getConf())));
         rrt.setDomainList(RecipientRewriteTableFixture.domainListForCucumberTests());
         return rrt;
     }


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


[james-project] 13/15: JAMES-3078 Reactify GetVacation

Posted by bt...@apache.org.
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 30f600aa1704541b2fda91435958662ec4107a56
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sun Mar 22 18:08:52 2020 +0700

    JAMES-3078 Reactify GetVacation
---
 .../draft/methods/GetVacationResponseMethod.java   | 32 +++++++++++-----------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
index 18c3017..1b11bd3 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
@@ -19,8 +19,6 @@
 
 package org.apache.james.jmap.draft.methods;
 
-import java.util.stream.Stream;
-
 import javax.inject.Inject;
 
 import org.apache.james.jmap.api.vacation.AccountId;
@@ -32,11 +30,13 @@ import org.apache.james.jmap.draft.model.MethodCallId;
 import org.apache.james.jmap.draft.model.VacationResponse;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.metrics.api.MetricFactory;
-import org.apache.james.util.MDCBuilder;
 import org.apache.james.util.date.ZonedDateTimeProvider;
 
 import com.google.common.base.Preconditions;
 
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
 public class GetVacationResponseMethod implements Method {
 
     public static final Request.Name METHOD_NAME = Request.name("getVacationResponse");
@@ -64,27 +64,27 @@ public class GetVacationResponseMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Flux<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(methodCallId);
         Preconditions.checkNotNull(mailboxSession);
         Preconditions.checkArgument(request instanceof GetVacationRequest);
 
+        return Flux.from(metricFactory.runPublishingTimerMetricLogP99(JMAP_PREFIX + METHOD_NAME.getName(),
+            process(mailboxSession)
+                .flatMapMany(response -> Flux.just(JmapResponse.builder()
+                    .methodCallId(methodCallId)
+                    .responseName(RESPONSE_NAME)
+                    .response(response)
+                    .build()))));
+    }
 
-        return MDCBuilder.create()
-            .addContext(MDCBuilder.ACTION, "VACATION")
-            .wrapArround(
-                () -> metricFactory.runPublishingTimerMetricLogP99(JMAP_PREFIX + METHOD_NAME.getName(),
-                    () -> Stream.of(JmapResponse.builder()
-                        .methodCallId(methodCallId)
-                        .responseName(RESPONSE_NAME)
-                        .response(process(mailboxSession))
-                        .build())))
-            .get();
+    private Mono<GetVacationResponse> process(MailboxSession mailboxSession) {
+        return vacationRepository.retrieveVacation(AccountId.fromUsername(mailboxSession.getUser()))
+            .map(vacation -> asVacationResponse(mailboxSession, vacation));
     }
 
-    private GetVacationResponse process(MailboxSession mailboxSession) {
-        Vacation vacation = vacationRepository.retrieveVacation(AccountId.fromUsername(mailboxSession.getUser())).block();
+    private GetVacationResponse asVacationResponse(MailboxSession mailboxSession, Vacation vacation) {
         return GetVacationResponse.builder()
             .accountId(mailboxSession.getUser().asString())
             .vacationResponse(VacationResponse.builder()


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


[james-project] 11/15: JAMES-3105 Additional sanitizing for mailbox counters

Posted by bt...@apache.org.
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 ee4510bde05e0a83ad4c669820fb70f32c6d4cce
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sat Mar 28 19:17:37 2020 +0700

    JAMES-3105 Additional sanitizing for mailbox counters
---
 .../james/mailbox/model/MailboxCounters.java       | 32 +++++++++++
 .../james/mailbox/model/MailboxCountersTest.java   | 64 ++++++++++++++++++++++
 .../james/jmap/draft/model/MailboxFactory.java     |  7 ++-
 3 files changed, 100 insertions(+), 3 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxCounters.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxCounters.java
index d05eb65..3cceed5 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxCounters.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxCounters.java
@@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
 
 public class MailboxCounters {
     private static final Logger LOGGER = LoggerFactory.getLogger(MailboxCounters.class);
@@ -61,6 +62,20 @@ public class MailboxCounters {
         }
     }
 
+    public static class Sanitized extends MailboxCounters {
+        static Sanitized of(MailboxId mailboxId, long count, long unseen) {
+            Preconditions.checkArgument(count >= 0, "'count' need to be strictly positive");
+            Preconditions.checkArgument(unseen >= 0, "'count' need to be strictly positive");
+            Preconditions.checkArgument(count >= unseen, "'unseen' cannot exceed 'count'");
+
+            return new Sanitized(mailboxId, count, unseen);
+        }
+
+        private Sanitized(MailboxId mailboxId, long count, long unseen) {
+            super(mailboxId, count, unseen);
+        }
+    }
+
     public static Builder.RequireMailboxId builder() {
         return mailboxId -> count -> unseen -> new Builder.FinalStage(count, unseen, mailboxId);
     }
@@ -87,6 +102,23 @@ public class MailboxCounters {
         return unseen;
     }
 
+    public MailboxCounters.Sanitized sanitize() {
+        if (!isValid()) {
+            LOGGER.warn("Invalid mailbox counters for {} : {} / {}", mailboxId, unseen, count);
+        }
+        long sanitizedCount = Math.max(count, 0);
+        long positiveUnseen = Math.max(unseen, 0);
+        long sanitizedUnseen = Math.min(positiveUnseen, sanitizedCount);
+
+        return Sanitized.of(mailboxId, sanitizedCount, sanitizedUnseen);
+    }
+
+    private boolean isValid() {
+        return count >= 0
+            && unseen >= 0
+            && count >= unseen;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof MailboxCounters) {
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxCountersTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxCountersTest.java
index b7efa25..d08b988 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxCountersTest.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxCountersTest.java
@@ -20,14 +20,78 @@
 
 package org.apache.james.mailbox.model;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
 import org.junit.jupiter.api.Test;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 
 class MailboxCountersTest {
 
+    public static final TestId MAILBOX_ID = TestId.of(36);
+
     @Test
     void mailboxCountersShouldRespectBeanContract() {
         EqualsVerifier.forClass(MailboxCounters.class).verify();
     }
+
+    @Test
+    void sanitizeShouldCorrectNegativeCount() {
+        assertThat(MailboxCounters.builder()
+                .mailboxId(MAILBOX_ID)
+                .count(-1)
+                .unseen(0)
+                .build()
+                .sanitize())
+            .isEqualTo(MailboxCounters.builder()
+                .mailboxId(MAILBOX_ID)
+                .count(0)
+                .unseen(0)
+                .build());
+    }
+
+    @Test
+    void sanitizeShouldCorrectNegativeUnseen() {
+        assertThat(MailboxCounters.builder()
+                .mailboxId(MAILBOX_ID)
+                .count(12)
+                .unseen(-1)
+                .build()
+                .sanitize())
+            .isEqualTo(MailboxCounters.builder()
+                .mailboxId(MAILBOX_ID)
+                .count(12)
+                .unseen(0)
+                .build());
+    }
+
+    @Test
+    void sanitizeShouldCorrectUnseenExceedingCount() {
+        assertThat(MailboxCounters.builder()
+                .mailboxId(MAILBOX_ID)
+                .count(12)
+                .unseen(36)
+                .build()
+                .sanitize())
+            .isEqualTo(MailboxCounters.builder()
+                .mailboxId(MAILBOX_ID)
+                .count(12)
+                .unseen(12)
+                .build());
+    }
+
+    @Test
+    void sanitizeShouldNoopWhenValid() {
+        assertThat(MailboxCounters.builder()
+                .mailboxId(MAILBOX_ID)
+                .count(36)
+                .unseen(12)
+                .build()
+                .sanitize())
+            .isEqualTo(MailboxCounters.builder()
+                .mailboxId(MAILBOX_ID)
+                .count(36)
+                .unseen(12)
+                .build());
+    }
 }
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 c0ea2b8..456f58a 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
@@ -110,8 +110,9 @@ public class MailboxFactory {
                 MailboxPath mailboxPath = mailboxMetaData.map(MailboxMetaData::getPath)
                     .orElseGet(Throwing.supplier(() -> retrieveCachedMailbox(mailboxId, mailbox).getMailboxPath()).sneakyThrow());
 
-                MailboxCounters mailboxCounters = mailboxMetaData.map(MailboxMetaData::getCounters)
-                    .orElseGet(Throwing.supplier(() -> retrieveCachedMailbox(mailboxId, mailbox).getMailboxCounters(session)).sneakyThrow());
+                MailboxCounters.Sanitized mailboxCounters = mailboxMetaData.map(MailboxMetaData::getCounters)
+                    .orElseGet(Throwing.supplier(() -> retrieveCachedMailbox(mailboxId, mailbox).getMailboxCounters(session)).sneakyThrow())
+                    .sanitize();
 
                 return Optional.of(mailboxFactory.from(
                     mailboxId,
@@ -163,7 +164,7 @@ public class MailboxFactory {
 
     private Mailbox from(MailboxId mailboxId,
                          MailboxPath mailboxPath,
-                         MailboxCounters mailboxCounters,
+                         MailboxCounters.Sanitized mailboxCounters,
                          MailboxACL resolvedAcl,
                          Optional<List<MailboxMetaData>> userMailboxesMetadata,
                          QuotaLoader quotaLoader,


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


[james-project] 06/15: JAMES-2648 Avoid reading schemaVersion upon each alias resolution

Posted by bt...@apache.org.
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 c84c807cc7210be2bcc35d65a44e7248676185c8
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Mar 30 11:00:02 2020 +0700

    JAMES-2648 Avoid reading schemaVersion upon each alias resolution
    
    Reading it once upon James startup is enough for up-to-date James server.
    
    We shall keep this pattern when James is not yet up to date.
---
 .../cassandra/CassandraRecipientRewriteTable.java  | 31 ++++++++++++++++------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
index 5b751a3..d28e2e2 100644
--- a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
@@ -44,14 +44,17 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
     private final CassandraRecipientRewriteTableDAO cassandraRecipientRewriteTableDAO;
     private final CassandraMappingsSourcesDAO cassandraMappingsSourcesDAO;
     private final CassandraSchemaVersionDAO cassandraSchemaVersionDAO;
+    private final SchemaVersion initialSchemaVersion;
 
     @Inject
-    public CassandraRecipientRewriteTable(CassandraRecipientRewriteTableDAO cassandraRecipientRewriteTableDAO,
-                                          CassandraMappingsSourcesDAO cassandraMappingsSourcesDAO,
-                                          CassandraSchemaVersionDAO cassandraSchemaVersionDAO) {
+    CassandraRecipientRewriteTable(CassandraRecipientRewriteTableDAO cassandraRecipientRewriteTableDAO,
+                                   CassandraMappingsSourcesDAO cassandraMappingsSourcesDAO,
+                                   CassandraSchemaVersionDAO cassandraSchemaVersionDAO) {
         this.cassandraRecipientRewriteTableDAO = cassandraRecipientRewriteTableDAO;
         this.cassandraMappingsSourcesDAO = cassandraMappingsSourcesDAO;
         this.cassandraSchemaVersionDAO = cassandraSchemaVersionDAO;
+
+        initialSchemaVersion = retrieveCurrentSchemaVersion();
     }
 
     @Override
@@ -98,14 +101,26 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
         Preconditions.checkArgument(listSourcesSupportedType.contains(mapping.getType()),
             "Not supported mapping of type %s", mapping.getType());
 
-        SchemaVersion schemaVersion = cassandraSchemaVersionDAO.getCurrentSchemaVersion()
-            .block()
-            .orElse(CassandraSchemaVersionManager.MIN_VERSION);
-
-        if (schemaVersion.isBefore(MAPPINGS_SOURCES_SUPPORTED_VERSION)) {
+        if (isLegacy()) {
             return super.listSources(mapping);
         }
 
         return cassandraMappingsSourcesDAO.retrieveSources(mapping).toStream();
     }
+
+    private boolean isLegacy() {
+        return isLegacy(initialSchemaVersion)
+            // If we started with a legacy james then maybe schema version had been updated since then
+            || isLegacy(retrieveCurrentSchemaVersion());
+    }
+
+    private boolean isLegacy(SchemaVersion schemaVersion) {
+        return schemaVersion.isBefore(MAPPINGS_SOURCES_SUPPORTED_VERSION);
+    }
+
+    private SchemaVersion retrieveCurrentSchemaVersion() {
+        return cassandraSchemaVersionDAO.getCurrentSchemaVersion()
+            .block()
+            .orElse(CassandraSchemaVersionManager.MIN_VERSION);
+    }
 }


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


[james-project] 04/15: JAMES-2632 Avoid reading MailboxPathV1Table if not needed

Posted by bt...@apache.org.
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 a8b84c4862ef44ac0a94d0646233ef718e6465e2
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Mar 30 11:57:17 2020 +0700

    JAMES-2632 Avoid reading MailboxPathV1Table if not needed
    
    If james starts with an up-to-date Cassandra schema, it can skip reads into MailboxPathV1
    
    According to glowroot, these unneeded operations accounts for 5% of
    GetMailboxes time.
---
 .../CassandraMailboxSessionMapperFactory.java      |  7 ++--
 .../cassandra/mail/CassandraMailboxMapper.java     | 36 +++++++++++++++----
 .../CassandraSubscriptionManagerTest.java          |  3 ++
 .../mail/CassandraMailboxMapperGenericTest.java    | 40 +++++++++++++++++-----
 .../cassandra/mail/CassandraMailboxMapperTest.java |  4 ++-
 .../mail/migration/MailboxPathV2MigrationTest.java |  4 ++-
 6 files changed, 75 insertions(+), 19 deletions(-)

diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
index 86824de..6086ba4 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
@@ -23,6 +23,7 @@ import javax.inject.Inject;
 
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.blob.api.BlobStore;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper;
@@ -92,6 +93,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa
     private final CassandraAttachmentOwnerDAO ownerDAO;
     private final CassandraACLMapper aclMapper;
     private final CassandraUserMailboxRightsDAO userMailboxRightsDAO;
+    private final CassandraSchemaVersionDAO versionDAO;
     private final CassandraUtils cassandraUtils;
     private final CassandraConfiguration cassandraConfiguration;
 
@@ -105,7 +107,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa
                                                 BlobStore blobStore, CassandraAttachmentMessageIdDAO attachmentMessageIdDAO,
                                                 CassandraAttachmentOwnerDAO ownerDAO, CassandraACLMapper aclMapper,
                                                 CassandraUserMailboxRightsDAO userMailboxRightsDAO,
-                                                CassandraUtils cassandraUtils, CassandraConfiguration cassandraConfiguration) {
+                                                CassandraSchemaVersionDAO versionDAO, CassandraUtils cassandraUtils, CassandraConfiguration cassandraConfiguration) {
         this.uidProvider = uidProvider;
         this.modSeqProvider = modSeqProvider;
         this.session = session;
@@ -126,6 +128,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa
         this.attachmentMessageIdDAO = attachmentMessageIdDAO;
         this.aclMapper = aclMapper;
         this.userMailboxRightsDAO = userMailboxRightsDAO;
+        this.versionDAO = versionDAO;
         this.cassandraUtils = cassandraUtils;
         this.ownerDAO = ownerDAO;
         this.cassandraConfiguration = cassandraConfiguration;
@@ -165,7 +168,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa
 
     @Override
     public MailboxMapper createMailboxMapper(MailboxSession mailboxSession) {
-        return new CassandraMailboxMapper(mailboxDAO, mailboxPathDAO, mailboxPathV2DAO, userMailboxRightsDAO, aclMapper);
+        return new CassandraMailboxMapper(mailboxDAO, mailboxPathDAO, mailboxPathV2DAO, userMailboxRightsDAO, aclMapper, versionDAO);
     }
 
     @Override
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
index 7a3f7ea..8e2d0b5 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
@@ -25,6 +25,9 @@ import java.util.List;
 import javax.inject.Inject;
 
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
+import org.apache.james.backends.cassandra.versions.SchemaVersion;
 import org.apache.james.core.Username;
 import org.apache.james.mailbox.acl.ACLDiff;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
@@ -54,33 +57,47 @@ public class CassandraMailboxMapper implements MailboxMapper {
     private static final int MAX_RETRY = 5;
     private static final Duration MIN_RETRY_BACKOFF = Duration.ofMillis(10);
     private static final Duration MAX_RETRY_BACKOFF = Duration.ofMillis(1000);
+    private static final SchemaVersion MAILBOX_PATH_V_2_MIGRATION_PERFORMED_VERSION = new SchemaVersion(6);
 
     private final CassandraMailboxDAO mailboxDAO;
     private final CassandraMailboxPathDAOImpl mailboxPathDAO;
     private final CassandraMailboxPathV2DAO mailboxPathV2DAO;
     private final CassandraACLMapper cassandraACLMapper;
     private final CassandraUserMailboxRightsDAO userMailboxRightsDAO;
+    private final boolean needMailboxPathV1Support;
 
     @Inject
-    public CassandraMailboxMapper(CassandraMailboxDAO mailboxDAO, CassandraMailboxPathDAOImpl mailboxPathDAO, CassandraMailboxPathV2DAO mailboxPathV2DAO, CassandraUserMailboxRightsDAO userMailboxRightsDAO, CassandraACLMapper aclMapper) {
+    public CassandraMailboxMapper(CassandraMailboxDAO mailboxDAO, CassandraMailboxPathDAOImpl mailboxPathDAO, CassandraMailboxPathV2DAO mailboxPathV2DAO, CassandraUserMailboxRightsDAO userMailboxRightsDAO, CassandraACLMapper aclMapper, CassandraSchemaVersionDAO versionDAO) {
         this.mailboxDAO = mailboxDAO;
         this.mailboxPathDAO = mailboxPathDAO;
         this.mailboxPathV2DAO = mailboxPathV2DAO;
         this.userMailboxRightsDAO = userMailboxRightsDAO;
         this.cassandraACLMapper = aclMapper;
+
+        this.needMailboxPathV1Support = versionDAO.getCurrentSchemaVersion()
+            .block()
+            .orElse(CassandraSchemaVersionManager.MIN_VERSION)
+            .isBefore(MAILBOX_PATH_V_2_MIGRATION_PERFORMED_VERSION);
     }
 
     @Override
     public void delete(Mailbox mailbox) {
         CassandraId mailboxId = (CassandraId) mailbox.getMailboxId();
-        Flux.merge(
-                mailboxPathDAO.delete(mailbox.generateAssociatedPath()),
-                mailboxPathV2DAO.delete(mailbox.generateAssociatedPath()))
+        deletePath(mailbox)
             .thenEmpty(mailboxDAO.delete(mailboxId)
                 .retryBackoff(MAX_RETRY, MIN_RETRY_BACKOFF, MAX_RETRY_BACKOFF))
             .block();
     }
 
+    private Flux<Void> deletePath(Mailbox mailbox) {
+        if (needMailboxPathV1Support) {
+            return Flux.merge(
+                mailboxPathDAO.delete(mailbox.generateAssociatedPath()),
+                mailboxPathV2DAO.delete(mailbox.generateAssociatedPath()));
+        }
+        return Flux.from(mailboxPathV2DAO.delete(mailbox.generateAssociatedPath()));
+    }
+
     @Override
     public Mono<Mailbox> findMailboxByPath(MailboxPath path) {
         return mailboxPathV2DAO.retrieveId(path)
@@ -137,8 +154,7 @@ public class CassandraMailboxMapper implements MailboxMapper {
         String fixedNamespace = query.getFixedNamespace();
         Username fixedUser = query.getFixedUser();
 
-        return Flux.concat(mailboxPathV2DAO.listUserMailboxes(fixedNamespace, fixedUser),
-                mailboxPathDAO.listUserMailboxes(fixedNamespace, fixedUser))
+        return listPaths(fixedNamespace, fixedUser)
             .filter(idAndPath -> query.isPathMatch(idAndPath.getMailboxPath()))
             .distinct(CassandraIdAndPath::getMailboxPath)
             .concatMap(this::retrieveMailbox)
@@ -146,6 +162,14 @@ public class CassandraMailboxMapper implements MailboxMapper {
             .block();
     }
 
+    private Flux<CassandraIdAndPath> listPaths(String fixedNamespace, Username fixedUser) {
+        if (needMailboxPathV1Support) {
+            return Flux.concat(mailboxPathV2DAO.listUserMailboxes(fixedNamespace, fixedUser),
+                mailboxPathDAO.listUserMailboxes(fixedNamespace, fixedUser));
+        }
+        return mailboxPathV2DAO.listUserMailboxes(fixedNamespace, fixedUser);
+    }
+
     private Mono<Mailbox> retrieveMailbox(CassandraIdAndPath idAndPath) {
         return retrieveMailbox(idAndPath.getCassandraId())
             .switchIfEmpty(ReactorUtils.executeAndEmpty(
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 33f1022..44e1063 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
@@ -22,6 +22,7 @@ package org.apache.james.mailbox.cassandra;
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.blob.api.BlobStore;
 import org.apache.james.mailbox.SubscriptionManager;
 import org.apache.james.mailbox.SubscriptionManagerContract;
@@ -86,6 +87,7 @@ class CassandraSubscriptionManagerTest implements SubscriptionManagerContract {
         BlobStore blobStore = null;
         CassandraUidProvider uidProvider = null;
         CassandraModSeqProvider modSeqProvider = null;
+        CassandraSchemaVersionDAO versionDAO = null;
 
         subscriptionManager = new StoreSubscriptionManager(
             new CassandraMailboxSessionMapperFactory(
@@ -110,6 +112,7 @@ class CassandraSubscriptionManagerTest implements SubscriptionManagerContract {
                 ownerDAO,
                 aclMapper,
                 userMailboxRightsDAO,
+                versionDAO,
                 CassandraUtils.WITH_DEFAULT_CONFIGURATION,
                 CassandraConfiguration.DEFAULT_CONFIGURATION));
     }
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperGenericTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperGenericTest.java
index af2d274..87c6fc3 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperGenericTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperGenericTest.java
@@ -21,7 +21,9 @@ package org.apache.james.mailbox.cassandra.mail;
 
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
+import org.apache.james.backends.cassandra.versions.SchemaVersion;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.mail.utils.GuiceUtils;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
@@ -31,10 +33,10 @@ import org.apache.james.mailbox.cassandra.modules.CassandraUidModule;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.apache.james.mailbox.store.mail.model.MailboxMapperTest;
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-class CassandraMailboxMapperGenericTest extends MailboxMapperTest {
-
+class CassandraMailboxMapperGenericTest {
     private static final CassandraModule MODULES = CassandraModule.aggregateModules(
         CassandraSchemaVersionModule.MODULE,
         CassandraAclModule.MODULE,
@@ -45,14 +47,34 @@ class CassandraMailboxMapperGenericTest extends MailboxMapperTest {
     @RegisterExtension
     static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(MODULES);
 
-    @Override
-    protected MailboxMapper createMailboxMapper() {
-        return GuiceUtils.testInjector(cassandraCluster.getCassandraCluster())
-            .getInstance(CassandraMailboxMapper.class);
+    @Nested
+    class V5 extends MailboxMapperTest {
+        @Override
+        protected MailboxMapper createMailboxMapper() {
+            return GuiceUtils.testInjector(cassandraCluster.getCassandraCluster())
+                .getInstance(CassandraMailboxMapper.class);
+        }
+
+        @Override
+        protected MailboxId generateId() {
+            return CassandraId.timeBased();
+        }
     }
 
-    @Override
-    protected MailboxId generateId() {
-        return CassandraId.timeBased();
+    @Nested
+    class V7 extends MailboxMapperTest {
+        @Override
+        protected MailboxMapper createMailboxMapper() {
+            new CassandraSchemaVersionDAO(cassandraCluster.getCassandraCluster().getConf())
+                .updateVersion(new SchemaVersion(7))
+                .block();
+            return GuiceUtils.testInjector(cassandraCluster.getCassandraCluster())
+                .getInstance(CassandraMailboxMapper.class);
+        }
+
+        @Override
+        protected MailboxId generateId() {
+            return CassandraId.timeBased();
+        }
     }
 }
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
index 1675f44..9a9fcf2 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
@@ -35,6 +35,7 @@ import org.apache.james.backends.cassandra.Scenario;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.core.Username;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
@@ -104,7 +105,8 @@ class CassandraMailboxMapperTest {
             mailboxPathDAO,
             mailboxPathV2DAO,
             userMailboxRightsDAO,
-            aclMapper);
+            aclMapper,
+            new CassandraSchemaVersionDAO(cassandra.getConf()));
     }
 
     @Nested
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/MailboxPathV2MigrationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/MailboxPathV2MigrationTest.java
index 81bab1c..d65cb06 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/MailboxPathV2MigrationTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/MailboxPathV2MigrationTest.java
@@ -26,6 +26,7 @@ import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
+import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.core.Username;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
@@ -83,7 +84,8 @@ class MailboxPathV2MigrationTest {
             daoV1,
             daoV2,
             userMailboxRightsDAO,
-            new CassandraACLMapper(cassandra.getConf(), userMailboxRightsDAO, CassandraConfiguration.DEFAULT_CONFIGURATION));
+            new CassandraACLMapper(cassandra.getConf(), userMailboxRightsDAO, CassandraConfiguration.DEFAULT_CONFIGURATION),
+            new CassandraSchemaVersionDAO(cassandra.getConf()));
     }
 
     @Test


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


[james-project] 10/15: JAMES-3105 Staged builder for mailbox counters

Posted by bt...@apache.org.
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 b426d6bb9b2eca5049fa70f318ed94800de44e05
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sat Mar 28 19:17:05 2020 +0700

    JAMES-3105 Staged builder for mailbox counters
---
 .../james/mailbox/model/MailboxCounters.java       | 52 ++++++++++++----------
 .../cassandra/mail/CassandraMailboxCounterDAO.java |  2 +-
 .../mail/CassandraMailboxCounterDAOTest.java       | 28 ++++++------
 .../james/mailbox/store/StoreMessageManager.java   |  2 +-
 4 files changed, 45 insertions(+), 39 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxCounters.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxCounters.java
index 6b5f0fe..d05eb65 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxCounters.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxCounters.java
@@ -19,44 +19,50 @@
 
 package org.apache.james.mailbox.model;
 
-import java.util.Optional;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
 
 public class MailboxCounters {
+    private static final Logger LOGGER = LoggerFactory.getLogger(MailboxCounters.class);
 
-    public static class Builder {
-        private Optional<Long> count = Optional.empty();
-        private Optional<Long> unseen = Optional.empty();
-        private Optional<MailboxId> mailboxId = Optional.empty();
-
-        public Builder mailboxId(MailboxId mailboxId) {
-            this.mailboxId = Optional.of(mailboxId);
-            return this;
+    public interface Builder {
+        @FunctionalInterface
+        interface RequireMailboxId {
+            RequireCount mailboxId(MailboxId mailboxId);
         }
 
-        public Builder count(long count) {
-            this.count = Optional.of(count);
-            return this;
+        @FunctionalInterface
+        interface RequireCount {
+            RequireUnseen count(long count);
         }
 
-        public Builder unseen(long unseen) {
-            this.unseen = Optional.of(unseen);
-            return this;
+        @FunctionalInterface
+        interface RequireUnseen {
+            FinalStage unseen(long unseen);
         }
 
-        public MailboxCounters build() {
-            Preconditions.checkState(count.isPresent(), "count is compulsory");
-            Preconditions.checkState(unseen.isPresent(), "unseen is compulsory");
-            Preconditions.checkState(mailboxId.isPresent(), "mailboxId is compulsory");
-            return new MailboxCounters(mailboxId.get(), count.get(), unseen.get());
+        class FinalStage {
+            private final long count;
+            private final long unseen;
+            private final MailboxId mailboxId;
+
+            FinalStage(long count, long unseen, MailboxId mailboxId) {
+                this.count = count;
+                this.unseen = unseen;
+                this.mailboxId = mailboxId;
+            }
+
+            public MailboxCounters build() {
+                return new MailboxCounters(mailboxId, count, unseen);
+            }
         }
     }
 
-    public static Builder builder() {
-        return new Builder();
+    public static Builder.RequireMailboxId builder() {
+        return mailboxId -> count -> unseen -> new Builder.FinalStage(count, unseen, mailboxId);
     }
 
     private final MailboxId mailboxId;
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 c8898a4..e9fb398 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
@@ -122,9 +122,9 @@ public class CassandraMailboxCounterDAO {
 
     private MailboxCounters emptyCounters(CassandraId mailboxId) {
         return MailboxCounters.builder()
+            .mailboxId(mailboxId)
             .count(0)
             .unseen(0)
-            .mailboxId(mailboxId)
             .build();
     }
 
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxCounterDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxCounterDAOTest.java
index 7bc43dc..558e58a 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxCounterDAOTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxCounterDAOTest.java
@@ -243,9 +243,9 @@ class CassandraMailboxCounterDAOTest {
     @Test
     void resetCountersShouldNoopWhenZeroAndNoData() {
         MailboxCounters counters = MailboxCounters.builder()
-            .unseen(0)
-            .count(0)
             .mailboxId(MAILBOX_ID)
+            .count(0)
+            .unseen(0)
             .build();
 
         testee.resetCounters(counters).block();
@@ -257,9 +257,9 @@ class CassandraMailboxCounterDAOTest {
     @Test
     void resetCountersShouldNoopWhenZeroAndZeroData() {
         MailboxCounters counters = MailboxCounters.builder()
-            .unseen(0)
-            .count(0)
             .mailboxId(MAILBOX_ID)
+            .count(0)
+            .unseen(0)
             .build();
 
         testee.incrementUnseen(MAILBOX_ID).block();
@@ -274,9 +274,9 @@ class CassandraMailboxCounterDAOTest {
     @Test
     void resetCountersShouldReInitCountWhenNothing() {
         MailboxCounters counters = MailboxCounters.builder()
-            .unseen(45)
-            .count(78)
             .mailboxId(MAILBOX_ID)
+            .count(78)
+            .unseen(45)
             .build();
 
         testee.resetCounters(counters).block();
@@ -288,9 +288,9 @@ class CassandraMailboxCounterDAOTest {
     @Test
     void resetCountersShouldReInitCountWhenData() {
         MailboxCounters counters = MailboxCounters.builder()
-            .unseen(45)
-            .count(78)
             .mailboxId(MAILBOX_ID)
+            .count(78)
+            .unseen(45)
             .build();
 
         testee.incrementCount(MAILBOX_ID).block();
@@ -305,9 +305,9 @@ class CassandraMailboxCounterDAOTest {
     @Test
     void resetCountersShouldBeIdempotent() {
         MailboxCounters counters = MailboxCounters.builder()
-            .unseen(45)
-            .count(78)
             .mailboxId(MAILBOX_ID)
+            .count(78)
+            .unseen(45)
             .build();
 
         testee.resetCounters(counters).block();
@@ -320,9 +320,9 @@ class CassandraMailboxCounterDAOTest {
     @Test
     void resetCountersShouldReInitCountWhenZeroUnseen() {
         MailboxCounters counters = MailboxCounters.builder()
-            .unseen(0)
-            .count(78)
             .mailboxId(MAILBOX_ID)
+            .count(78)
+            .unseen(0)
             .build();
 
         testee.incrementCount(MAILBOX_ID).block();
@@ -337,9 +337,9 @@ class CassandraMailboxCounterDAOTest {
     @Test
     void resetCountersShouldReInitCountWhenZeroCount() {
         MailboxCounters counters = MailboxCounters.builder()
-            .unseen(46)
-            .count(0)
             .mailboxId(MAILBOX_ID)
+            .count(0)
+            .unseen(46)
             .build();
 
         testee.incrementCount(MAILBOX_ID).block();
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
index f9f7d71..bb139fc 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
@@ -220,8 +220,8 @@ public class StoreMessageManager implements MessageManager {
         }
         return MailboxCounters.builder()
             .mailboxId(mailbox.getMailboxId())
-            .unseen(0)
             .count(0)
+            .unseen(0)
             .build();
     }
 


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


[james-project] 03/15: JAMES-2632 Lazy loading for backend parentId computation

Posted by bt...@apache.org.
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 5e670d124058ae917d31fc1960292e88abc53165
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Mar 30 11:46:01 2020 +0700

    JAMES-2632 Lazy loading for backend parentId computation
    
    The value was aggressively read for each mailbox read by GetMailboxes
    resulting in the following extra reads per mailbox:
     - mailboxPathV2
     - then mailbox
     - then acl
    
    This accounts according to glowroot to roughly 60% of GetMailboxes time
---
 .../james/jmap/draft/model/MailboxFactory.java     |  2 +-
 .../james/jmap/draft/model/MailboxFactoryTest.java | 30 ++++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

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 3d520bb..c0ea2b8 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
@@ -223,7 +223,7 @@ public class MailboxFactory {
         }
         MailboxPath parent = levels.get(levels.size() - 2);
         return userMailboxesMetadata.map(list -> retrieveParentFromMetadata(parent, list))
-            .orElse(retrieveParentFromBackend(mailboxSession, parent));
+            .orElseGet(Throwing.supplier(() -> retrieveParentFromBackend(mailboxSession, parent)).sneakyThrow());
     }
 
     private Optional<MailboxId> retrieveParentFromBackend(MailboxSession mailboxSession, MailboxPath parent) throws MailboxException {
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 24d8cb4..14d9d42 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
@@ -34,6 +34,7 @@ import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
 import org.apache.james.mailbox.manager.ManagerTestProvisionner;
 import org.apache.james.mailbox.model.MailboxACL;
+import org.apache.james.mailbox.model.MailboxCounters;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxMetaData;
 import org.apache.james.mailbox.model.MailboxPath;
@@ -198,6 +199,35 @@ public class MailboxFactoryTest {
     }
 
     @Test
+    public void buildShouldRelyOnPreloadedMailboxes() throws Exception {
+        MailboxPath inbox = MailboxPath.inbox(user);
+        Optional<MailboxId> inboxId = mailboxManager.createMailbox(inbox, mailboxSession);
+        Optional<MailboxId> otherId = mailboxManager.createMailbox(MailboxPath.forUser(user, "INBOX.child"), mailboxSession);
+
+        InMemoryId preLoadedId = InMemoryId.of(45);
+        Mailbox retrievedMailbox = sut.builder()
+            .id(otherId.get())
+            .session(mailboxSession)
+            .usingPreloadedMailboxesMetadata(Optional.of(ImmutableList.of(new MailboxMetaData(
+                inbox,
+                preLoadedId,
+                DELIMITER,
+                MailboxMetaData.Children.NO_INFERIORS,
+                MailboxMetaData.Selectability.NONE,
+                MailboxACL.EMPTY,
+                MailboxCounters.builder()
+                    .mailboxId(preLoadedId)
+                    .count(0)
+                    .unseen(0)
+                    .build()))))
+            .build()
+            .get();
+
+        assertThat(retrievedMailbox.getParentId())
+            .contains(preLoadedId);
+    }
+
+    @Test
     public void getNamespaceShouldReturnDelegatedNamespaceWhenUserMailboxPathAndUserMailboxSessionAreNotTheSame() throws Exception {
         MailboxPath inbox = MailboxPath.inbox(user);
         Optional<MailboxId> mailboxId = mailboxManager.createMailbox(inbox, mailboxSession);


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


[james-project] 15/15: JAMES-3078 MDC hierarchical MDC context for reactor

Posted by bt...@apache.org.
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 f08f82f9c3b7f30c4df824ba3b7be46fbeb9c5ae
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Mar 26 12:25:29 2020 +0700

    JAMES-3078 MDC hierarchical MDC context for reactor
---
 .../james/imap/processor/UnselectProcessor.java    |  3 +-
 .../java/org/apache/james/util/MDCBuilder.java     |  5 ++
 .../java/org/apache/james/util/ReactorUtils.java   | 50 +++++++++++++++++++
 .../org/apache/james/util/ReactorUtilsTest.java    | 50 +++++++++++++++++++
 .../draft/methods/GetVacationResponseMethod.java   |  5 +-
 .../draft/methods/SetVacationResponseMethod.java   |  8 ++-
 .../james/jmap/http/AuthenticationRoutes.java      | 57 ++++++++++++++--------
 .../org/apache/james/jmap/http/DownloadRoutes.java | 22 +++++++--
 .../org/apache/james/jmap/http/JMAPApiRoutes.java  | 16 +++---
 .../org/apache/james/jmap/http/LoggingHelper.java  | 46 +++++++++++++++++
 .../org/apache/james/jmap/http/UploadRoutes.java   | 12 ++++-
 .../apache/james/jmap/http/JMAPApiRoutesTest.java  |  9 ++--
 .../java/org/apache/james/jmap/JMAPRoutes.java     |  1 -
 13 files changed, 243 insertions(+), 41 deletions(-)

diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/UnselectProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/UnselectProcessor.java
index 64176c1..f6fa95a 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/UnselectProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/UnselectProcessor.java
@@ -66,8 +66,7 @@ public class UnselectProcessor extends AbstractMailboxProcessor<UnselectRequest>
 
     @Override
     protected Closeable addContextToMDC(UnselectRequest request) {
-        return MDCBuilder.create()
-            .addContext(MDCBuilder.ACTION, "UNSELECT")
+        return MDCBuilder.of(MDCBuilder.ACTION, "UNSELECT")
             .build();
     }
 }
diff --git a/server/container/util/src/main/java/org/apache/james/util/MDCBuilder.java b/server/container/util/src/main/java/org/apache/james/util/MDCBuilder.java
index bac3b4b..9bf6c5b 100644
--- a/server/container/util/src/main/java/org/apache/james/util/MDCBuilder.java
+++ b/server/container/util/src/main/java/org/apache/james/util/MDCBuilder.java
@@ -98,6 +98,11 @@ public class MDCBuilder {
         return new MDCBuilder();
     }
 
+    public static MDCBuilder of(String key, Object value) {
+        return create()
+            .addContext(key, value);
+    }
+
     private final ImmutableMap.Builder<String, String> contextMap = ImmutableMap.builder();
     private final ImmutableList.Builder<MDCBuilder> nestedBuilder = ImmutableList.builder();
 
diff --git a/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java b/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java
index a87ab17..df9c937 100644
--- a/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java
+++ b/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java
@@ -18,16 +18,23 @@
  ****************************************************************/
 package org.apache.james.util;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.util.Iterator;
 import java.util.Optional;
+import java.util.function.Consumer;
 
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
+import reactor.core.publisher.Signal;
+import reactor.util.context.Context;
 
 public class ReactorUtils {
+
+    public static final String MDC_KEY_PREFIX = "MDC-";
+
     public static <T> Mono<T> executeAndEmpty(Runnable runnable) {
         return Mono.fromRunnable(runnable).then(Mono.empty());
     }
@@ -100,4 +107,47 @@ public class ReactorUtils {
     private static int byteToInt(ByteBuffer buffer) {
         return buffer.get() & 0xff;
     }
+
+    public static Consumer<Signal<?>> logOnError(Consumer<Throwable> errorLogStatement) {
+        return signal -> {
+            if (!signal.isOnError()) {
+                return;
+            }
+            try {
+                try (Closeable mdc = retrieveMDCBuilder(signal).build()) {
+                    errorLogStatement.accept(signal.getThrowable());
+                }
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        };
+    }
+
+    public static Consumer<Signal<?>> log(Runnable logStatement) {
+        return signal -> {
+            try (Closeable mdc = retrieveMDCBuilder(signal).build()) {
+                logStatement.run();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        };
+    }
+
+    public static Context context(String keySuffix, MDCBuilder mdcBuilder) {
+        return Context.of(mdcKey(keySuffix), mdcBuilder);
+    }
+
+    private static String mdcKey(String value) {
+        return MDC_KEY_PREFIX + value;
+    }
+
+    private static MDCBuilder retrieveMDCBuilder(Signal<?> signal) {
+        return signal.getContext().stream()
+            .filter(entry -> entry.getKey() instanceof String)
+            .filter(entry -> entry.getValue() instanceof MDCBuilder)
+            .filter(entry -> ((String) entry.getKey()).startsWith(MDC_KEY_PREFIX))
+            .map(entry -> (MDCBuilder) entry.getValue())
+            .reduce(MDCBuilder.create(), MDCBuilder::addContext);
+    }
+
 }
diff --git a/server/container/util/src/test/java/org/apache/james/util/ReactorUtilsTest.java b/server/container/util/src/test/java/org/apache/james/util/ReactorUtilsTest.java
index 06edbc5..1ef5184 100644
--- a/server/container/util/src/test/java/org/apache/james/util/ReactorUtilsTest.java
+++ b/server/container/util/src/test/java/org/apache/james/util/ReactorUtilsTest.java
@@ -27,11 +27,13 @@ import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.IntStream;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.slf4j.MDC;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.primitives.Bytes;
@@ -280,4 +282,52 @@ class ReactorUtilsTest {
             assertThat(chunks).isEqualTo(expected);
         }
     }
+
+    @Nested
+    class MDCTest {
+        @Test
+        void contextShouldEnhanceMDC() {
+            String value = "value";
+            String key = "key";
+
+            Flux.just(1)
+                .doOnEach(ReactorUtils.log(() -> {
+                    assertThat(MDC.get(key)).isEqualTo(value);
+                }))
+                .subscriberContext(ReactorUtils.context("test", MDCBuilder.of(key, value)))
+                .blockLast();
+        }
+
+        @Test
+        void contextShouldNotOverwritePreviousKeys() {
+            String value1 = "value1";
+            String value2 = "value2";
+            String key = "key";
+
+            Flux.just(1)
+                .doOnEach(ReactorUtils.log(() -> {
+                    assertThat(MDC.get(key)).isEqualTo(value1);
+                }))
+                .subscriberContext(ReactorUtils.context("test", MDCBuilder.of(key, value1)))
+                .subscriberContext(ReactorUtils.context("test", MDCBuilder.of(key, value2)))
+                .blockLast();
+        }
+
+        @Test
+        void contextShouldCombineMDCs() {
+            String value1 = "value1";
+            String value2 = "value2";
+            String key1 = "key1";
+            String key2 = "key2";
+
+            Flux.just(1)
+                .doOnEach(ReactorUtils.log(() -> {
+                    assertThat(MDC.get(key1)).isEqualTo(value1);
+                    assertThat(MDC.get(key2)).isEqualTo(value2);
+                }))
+                .subscriberContext(ReactorUtils.context("test1", MDCBuilder.of(key1, value1)))
+                .subscriberContext(ReactorUtils.context("test2", MDCBuilder.of(key2, value2)))
+                .blockLast();
+        }
+    }
 }
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
index 1b11bd3..da38ebd 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.jmap.draft.methods;
 
+import static org.apache.james.jmap.http.LoggingHelper.jmapAction;
+
 import javax.inject.Inject;
 
 import org.apache.james.jmap.api.vacation.AccountId;
@@ -76,7 +78,8 @@ public class GetVacationResponseMethod implements Method {
                     .methodCallId(methodCallId)
                     .responseName(RESPONSE_NAME)
                     .response(response)
-                    .build()))));
+                    .build()))))
+            .subscriberContext(jmapAction("VACATION"));
     }
 
     private Mono<GetVacationResponse> process(MailboxSession mailboxSession) {
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
index d8952b8..4da3a22 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
@@ -19,6 +19,9 @@
 
 package org.apache.james.jmap.draft.methods;
 
+import static org.apache.james.jmap.http.LoggingHelper.jmapAction;
+import static org.apache.james.util.ReactorUtils.context;
+
 import javax.inject.Inject;
 
 import org.apache.james.jmap.api.vacation.AccountId;
@@ -32,6 +35,7 @@ import org.apache.james.jmap.draft.model.SetVacationResponse;
 import org.apache.james.jmap.draft.model.VacationResponse;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.util.MDCBuilder;
 
 import com.google.common.base.Preconditions;
 
@@ -77,7 +81,9 @@ public class SetVacationResponseMethod implements Method {
         SetVacationRequest setVacationRequest = (SetVacationRequest) request;
 
         return metricFactory.runPublishingTimerMetricLogP99(JMAP_PREFIX + METHOD_NAME.getName(),
-            () -> process(methodCallId, mailboxSession, setVacationRequest));
+            () -> process(methodCallId, mailboxSession, setVacationRequest)
+                .subscriberContext(jmapAction("SET_VACATION"))
+                .subscriberContext(context("set-vacation", MDCBuilder.of("update", setVacationRequest.getUpdate()))));
     }
 
     private Flux<JmapResponse> process(MethodCallId methodCallId, MailboxSession mailboxSession, SetVacationRequest setVacationRequest) {
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/AuthenticationRoutes.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/AuthenticationRoutes.java
index 5470969..db645dd 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/AuthenticationRoutes.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/AuthenticationRoutes.java
@@ -29,6 +29,11 @@ import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED;
 import static org.apache.james.jmap.HttpConstants.JSON_CONTENT_TYPE;
 import static org.apache.james.jmap.HttpConstants.JSON_CONTENT_TYPE_UTF8;
 import static org.apache.james.jmap.http.JMAPUrls.AUTHENTICATION;
+import static org.apache.james.jmap.http.LoggingHelper.jmapAction;
+import static org.apache.james.jmap.http.LoggingHelper.jmapAuthContext;
+import static org.apache.james.jmap.http.LoggingHelper.jmapContext;
+import static org.apache.james.util.ReactorUtils.log;
+import static org.apache.james.util.ReactorUtils.logOnError;
 
 import java.io.IOException;
 import java.util.Objects;
@@ -118,29 +123,40 @@ public class AuthenticationRoutes implements JMAPRoutes {
                     } else {
                         throw new RuntimeException(objectRequest.getClass() + " " + objectRequest);
                     }
-                })
-                .onErrorResume(BadRequestException.class, e -> handleBadRequest(response, e))
-                .onErrorResume(e -> handleInternalError(response, e))))
+                })))
+            .onErrorResume(BadRequestException.class, e -> handleBadRequest(response, e))
+            .doOnEach(logOnError(e -> LOGGER.error("Unexpected error", e)))
+            .onErrorResume(e -> handleInternalError(response, e))
+            .subscriberContext(jmapContext(request))
+            .subscriberContext(jmapAction("auth-post"))
             .subscribeOn(Schedulers.elastic());
     }
 
     private Mono<Void> returnEndPointsResponse(HttpServerRequest req, HttpServerResponse resp) {
-        try {
             return authenticator.authenticate(req)
-                .then(resp.status(OK)
-                    .header(CONTENT_TYPE, JSON_CONTENT_TYPE_UTF8)
-                    .sendString(Mono.just(mapper.writeValueAsString(EndPointsResponse
-                        .builder()
-                        .api(JMAPUrls.JMAP)
-                        .eventSource(JMAPUrls.NOT_IMPLEMENTED)
-                        .upload(JMAPUrls.UPLOAD)
-                        .download(JMAPUrls.DOWNLOAD)
-                        .build())))
-                    .then())
+                .flatMap(session -> returnEndPointsResponse(resp)
+                    .subscriberContext(jmapAuthContext(session)))
                 .onErrorResume(BadRequestException.class, e -> handleBadRequest(resp, e))
+                .doOnEach(logOnError(e -> LOGGER.error("Unexpected error", e)))
                 .onErrorResume(InternalErrorException.class, e -> handleInternalError(resp, e))
                 .onErrorResume(UnauthorizedException.class, e -> handleAuthenticationFailure(resp, e))
+                .subscriberContext(jmapContext(req))
+                .subscriberContext(jmapAction("returnEndPoints"))
                 .subscribeOn(Schedulers.elastic());
+    }
+
+    private Mono<Void> returnEndPointsResponse(HttpServerResponse resp) {
+        try {
+            return resp.status(OK)
+                .header(CONTENT_TYPE, JSON_CONTENT_TYPE_UTF8)
+                .sendString(Mono.just(mapper.writeValueAsString(EndPointsResponse
+                    .builder()
+                    .api(JMAPUrls.JMAP)
+                    .eventSource(JMAPUrls.NOT_IMPLEMENTED)
+                    .upload(JMAPUrls.UPLOAD)
+                    .download(JMAPUrls.DOWNLOAD)
+                    .build())))
+                .then();
         } catch (JsonProcessingException e) {
             throw new InternalErrorException("Error serializing endpoint response", e);
         }
@@ -151,8 +167,11 @@ public class AuthenticationRoutes implements JMAPRoutes {
 
         return authenticator.authenticate(req)
             .flatMap(session -> Mono.from(accessTokenManager.revoke(AccessToken.fromString(authorizationHeader)))
-                .then(resp.status(NO_CONTENT).send().then()))
+                    .then(resp.status(NO_CONTENT).send().then())
+                .subscriberContext(jmapAuthContext(session)))
             .onErrorResume(UnauthorizedException.class, e -> handleAuthenticationFailure(resp, e))
+            .subscriberContext(jmapContext(req))
+            .subscriberContext(jmapAction("auth-delete"))
             .subscribeOn(Schedulers.elastic());
     }
 
@@ -204,8 +223,8 @@ public class AuthenticationRoutes implements JMAPRoutes {
             case EXPIRED:
                 return returnForbiddenAuthentication(resp);
             case INVALID:
-                LOGGER.warn("Use of an invalid ContinuationToken : {}", request.getToken().serialize());
-                return returnUnauthorizedResponse(resp);
+                return returnUnauthorizedResponse(resp)
+                    .doOnEach(log(() -> LOGGER.warn("Use of an invalid ContinuationToken : {}", request.getToken().serialize())));
             case OK:
                 return manageAuthenticationResponse(request, resp);
             default:
@@ -221,8 +240,8 @@ public class AuthenticationRoutes implements JMAPRoutes {
                 if (success) {
                     return returnAccessTokenResponse(resp, username);
                 } else {
-                    LOGGER.info("Authentication failure for {}", username);
-                    return returnUnauthorizedResponse(resp);
+                    return returnUnauthorizedResponse(resp)
+                        .doOnEach(log(() -> LOGGER.info("Authentication failure for {}", username)));
                 }
             });
     }
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/DownloadRoutes.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/DownloadRoutes.java
index d639d16..57b99bd 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/DownloadRoutes.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/DownloadRoutes.java
@@ -23,6 +23,10 @@ import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
 import static io.netty.handler.codec.http.HttpResponseStatus.OK;
 import static org.apache.james.jmap.HttpConstants.TEXT_PLAIN_CONTENT_TYPE;
 import static org.apache.james.jmap.http.JMAPUrls.DOWNLOAD;
+import static org.apache.james.jmap.http.LoggingHelper.jmapAction;
+import static org.apache.james.jmap.http.LoggingHelper.jmapAuthContext;
+import static org.apache.james.jmap.http.LoggingHelper.jmapContext;
+import static org.apache.james.util.ReactorUtils.logOnError;
 
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
@@ -116,9 +120,13 @@ public class DownloadRoutes implements JMAPRoutes {
     private Mono<Void> post(HttpServerRequest request, HttpServerResponse response, DownloadPath downloadPath) {
         return authenticator.authenticate(request)
             .flatMap(session -> Mono.from(metricFactory.runPublishingTimerMetric("JMAP-download-post",
-                respondAttachmentAccessToken(session, downloadPath, response)))
-            .onErrorResume(InternalErrorException.class, e -> handleInternalError(response, e))
-            .onErrorResume(UnauthorizedException.class, e -> handleAuthenticationFailure(response, e)))
+                    respondAttachmentAccessToken(session, downloadPath, response)))
+                .subscriberContext(jmapAuthContext(session)))
+            .onErrorResume(UnauthorizedException.class, e -> handleAuthenticationFailure(response, e))
+            .doOnEach(logOnError(e -> LOGGER.error("Unexpected error", e)))
+            .onErrorResume(e -> handleInternalError(response, e))
+            .subscriberContext(jmapContext(request))
+            .subscriberContext(jmapAction("download-post"))
             .subscribeOn(Schedulers.elastic());
     }
 
@@ -142,9 +150,13 @@ public class DownloadRoutes implements JMAPRoutes {
     private Mono<Void> get(HttpServerRequest request, HttpServerResponse response, DownloadPath downloadPath) {
         return authenticator.authenticate(request)
             .flatMap(session -> Mono.from(metricFactory.runPublishingTimerMetric("JMAP-download-get",
-                download(session, downloadPath, response)))
-            .onErrorResume(InternalErrorException.class, e -> handleInternalError(response, e)))
+                    download(session, downloadPath, response)))
+                .subscriberContext(jmapAuthContext(session)))
             .onErrorResume(UnauthorizedException.class, e -> handleAuthenticationFailure(response, e))
+            .doOnEach(logOnError(e -> LOGGER.error("Unexpected error", e)))
+            .onErrorResume(e -> handleInternalError(response, e))
+            .subscriberContext(jmapContext(request))
+            .subscriberContext(jmapAction("download-get"))
             .subscribeOn(Schedulers.elastic());
     }
 
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JMAPApiRoutes.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JMAPApiRoutes.java
index 9973616..9a483e2 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JMAPApiRoutes.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JMAPApiRoutes.java
@@ -22,6 +22,9 @@ import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
 import static io.netty.handler.codec.http.HttpResponseStatus.OK;
 import static org.apache.james.jmap.HttpConstants.JSON_CONTENT_TYPE;
 import static org.apache.james.jmap.http.JMAPUrls.JMAP;
+import static org.apache.james.jmap.http.LoggingHelper.jmapAuthContext;
+import static org.apache.james.jmap.http.LoggingHelper.jmapContext;
+import static org.apache.james.util.ReactorUtils.logOnError;
 
 import java.io.IOException;
 
@@ -87,15 +90,16 @@ public class JMAPApiRoutes implements JMAPRoutes {
     private Mono<Void> post(HttpServerRequest request, HttpServerResponse response) {
         return authenticator.authenticate(request)
             .flatMap(session -> Flux.merge(
-                    userProvisioner.provisionUser(session),
-                    defaultMailboxesProvisioner.createMailboxesIfNeeded(session))
-                .then()
-                .thenReturn(session))
-            .flatMap(session -> Mono.from(metricFactory.runPublishingTimerMetric("JMAP-request",
-                post(request, response, session))))
+                userProvisioner.provisionUser(session),
+                defaultMailboxesProvisioner.createMailboxesIfNeeded(session))
+                .then(Mono.from(metricFactory.runPublishingTimerMetric("JMAP-request",
+                    post(request, response, session))))
+                .subscriberContext(jmapAuthContext(session)))
             .onErrorResume(BadRequestException.class, e -> handleBadRequest(response, e))
             .onErrorResume(UnauthorizedException.class, e -> handleAuthenticationFailure(response, e))
+            .doOnEach(logOnError(e -> LOGGER.error("Unexpected error", e)))
             .onErrorResume(e -> handleInternalError(response, e))
+            .subscriberContext(jmapContext(request))
             .subscribeOn(Schedulers.elastic());
     }
 
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/LoggingHelper.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/LoggingHelper.java
new file mode 100644
index 0000000..af504f63
--- /dev/null
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/LoggingHelper.java
@@ -0,0 +1,46 @@
+/****************************************************************
+ * 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.jmap.http;
+
+import static org.apache.james.util.ReactorUtils.context;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.util.MDCBuilder;
+
+import reactor.netty.http.server.HttpServerRequest;
+import reactor.util.context.Context;
+
+public interface LoggingHelper {
+    static Context jmapAuthContext(MailboxSession session) {
+        return context("JMAP_AUTH",
+            MDCBuilder.of(MDCBuilder.USER, session.getUser().asString()));
+    }
+
+    static Context jmapContext(HttpServerRequest req) {
+        return context("JMAP", MDCBuilder.create()
+            .addContext(MDCBuilder.PROTOCOL, "JMAP")
+            .addContext(MDCBuilder.IP, req.hostAddress().getHostString()));
+    }
+
+    static Context jmapAction(String action) {
+        return context("JMAP_ACTION",
+            MDCBuilder.of(MDCBuilder.ACTION, action));
+    }
+}
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/UploadRoutes.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/UploadRoutes.java
index f29ae56..ff0f306 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/UploadRoutes.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/UploadRoutes.java
@@ -23,6 +23,10 @@ import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
 import static io.netty.handler.codec.http.HttpResponseStatus.CREATED;
 import static org.apache.james.jmap.HttpConstants.JSON_CONTENT_TYPE_UTF8;
 import static org.apache.james.jmap.http.JMAPUrls.UPLOAD;
+import static org.apache.james.jmap.http.LoggingHelper.jmapAction;
+import static org.apache.james.jmap.http.LoggingHelper.jmapAuthContext;
+import static org.apache.james.jmap.http.LoggingHelper.jmapContext;
+import static org.apache.james.util.ReactorUtils.logOnError;
 
 import java.io.EOFException;
 import java.io.IOException;
@@ -91,11 +95,15 @@ public class UploadRoutes implements JMAPRoutes {
             return response.status(BAD_REQUEST).send();
         } else {
             return authenticator.authenticate(request)
-                .flatMap(session -> post(request, response, contentType, session))
+                .flatMap(session -> post(request, response, contentType, session)
+                    .subscriberContext(jmapAuthContext(session)))
                 .onErrorResume(CancelledUploadException.class, e -> handleCanceledUpload(response, e))
                 .onErrorResume(BadRequestException.class, e -> handleBadRequest(response, e))
                 .onErrorResume(UnauthorizedException.class, e -> handleAuthenticationFailure(response, e))
-                .onErrorResume(InternalErrorException.class, e -> handleInternalError(response, e))
+                .doOnEach(logOnError(e -> LOGGER.error("Unexpected error", e)))
+                .onErrorResume(e -> handleInternalError(response, e))
+                .subscriberContext(jmapContext(request))
+                .subscriberContext(jmapAction("upload-get"))
                 .subscribeOn(Schedulers.elastic());
         }
     }
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JMAPApiRoutesTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JMAPApiRoutesTest.java
index e8cafca..5cb214f 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JMAPApiRoutesTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JMAPApiRoutesTest.java
@@ -24,18 +24,19 @@ import static io.restassured.config.RestAssuredConfig.newConfig;
 import static org.apache.james.jmap.http.JMAPUrls.JMAP;
 import static org.hamcrest.Matchers.equalTo;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.nio.charset.StandardCharsets;
-import java.util.stream.Stream;
 
+import org.apache.james.core.Username;
 import org.apache.james.jmap.draft.methods.ErrorResponse;
 import org.apache.james.jmap.draft.methods.Method;
 import org.apache.james.jmap.draft.methods.RequestHandler;
 import org.apache.james.jmap.draft.model.InvocationResponse;
 import org.apache.james.jmap.draft.model.MethodCallId;
-import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MailboxSessionUtil;
 import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.After;
 import org.junit.Before;
@@ -85,8 +86,8 @@ public class JMAPApiRoutesTest {
             .setBasePath(JMAP)
             .build();
 
-        when(mockedAuthFilter.authenticate(any()))
-            .thenReturn(Mono.just(mock(MailboxSession.class)));
+        doReturn(Mono.just(MailboxSessionUtil.create(Username.of("bob"))))
+            .when(mockedAuthFilter).authenticate(any());
         when(mockedUserProvisionner.provisionUser(any()))
             .thenReturn(Mono.empty());
         when(mockedMailboxesProvisionner.createMailboxesIfNeeded(any()))
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPRoutes.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPRoutes.java
index 565c9c1..c42085d 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPRoutes.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPRoutes.java
@@ -48,7 +48,6 @@ public interface JMAPRoutes {
     Logger logger();
 
     default Mono<Void> handleInternalError(HttpServerResponse response, Throwable e) {
-        logger().error("Internal error", e);
         return response.status(INTERNAL_SERVER_ERROR).send();
     }
 


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


[james-project] 08/15: JAMES-2648 Avoid reading schemaVersion upon each alias resolution

Posted by bt...@apache.org.
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 52597104ee4a9544e6405547f83015706ce1c853
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Mar 31 14:50:56 2020 +0700

    JAMES-2648 Avoid reading schemaVersion upon each alias resolution
---
 .../james/rrt/cassandra/CassandraRecipientRewriteTable.java    |  2 +-
 .../rrt/cassandra/CassandraRecipientRewriteTableV6Test.java    |  7 ++-----
 ...va => CassandraRecipientRewriteTableV7BeforeStartTest.java} | 10 ++++------
 .../rrt/cassandra/CassandraRecipientRewriteTableV7Test.java    |  2 +-
 4 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
index 1997e53..0eac424 100644
--- a/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
+++ b/server/data/data-cassandra/src/main/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTable.java
@@ -110,7 +110,7 @@ public class CassandraRecipientRewriteTable extends AbstractRecipientRewriteTabl
     private boolean isLegacy() {
         return isLegacy(initialSchemaVersion)
             // If we started with a legacy james then maybe schema version had been updated since then
-            || isLegacy(versionManager.computeVersion());
+            && isLegacy(versionManager.computeVersion());
     }
 
     private boolean isLegacy(SchemaVersion schemaVersion) {
diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV6Test.java b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV6Test.java
index 69aea33..525eacb 100644
--- a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV6Test.java
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV6Test.java
@@ -63,14 +63,11 @@ public class CassandraRecipientRewriteTableV6Test extends AbstractRecipientRewri
     protected AbstractRecipientRewriteTable getRecipientRewriteTable() {
         CassandraSchemaVersionDAO cassandraSchemaVersionDAO = new CassandraSchemaVersionDAO(
             cassandra.getConf());
+        cassandraSchemaVersionDAO.updateVersion(SCHEMA_VERSION_V6).block();
 
-        CassandraRecipientRewriteTable rrt = new CassandraRecipientRewriteTable(
+        return new CassandraRecipientRewriteTable(
             new CassandraRecipientRewriteTableDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION),
             new CassandraMappingsSourcesDAO(cassandra.getConf()),
             new CassandraSchemaVersionManager(cassandraSchemaVersionDAO));
-
-        cassandraSchemaVersionDAO.updateVersion(SCHEMA_VERSION_V6);
-
-        return rrt;
     }
 }
diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7BeforeStartTest.java
similarity index 94%
copy from server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java
copy to server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7BeforeStartTest.java
index 063cb83..8510f4e 100644
--- a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7BeforeStartTest.java
@@ -33,7 +33,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 
-public class CassandraRecipientRewriteTableV7Test extends AbstractRecipientRewriteTableTest {
+public class CassandraRecipientRewriteTableV7BeforeStartTest extends AbstractRecipientRewriteTableTest {
     private static final SchemaVersion SCHEMA_VERSION_V7 = new SchemaVersion(7);
 
     private static final CassandraModule MODULE = CassandraModule.aggregateModules(
@@ -64,13 +64,11 @@ public class CassandraRecipientRewriteTableV7Test extends AbstractRecipientRewri
         CassandraSchemaVersionDAO cassandraSchemaVersionDAO = new CassandraSchemaVersionDAO(
             cassandra.getConf());
 
-        CassandraRecipientRewriteTable rrt = new CassandraRecipientRewriteTable(
+        cassandraSchemaVersionDAO.updateVersion(SCHEMA_VERSION_V7).block();
+
+        return new CassandraRecipientRewriteTable(
             new CassandraRecipientRewriteTableDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION),
             new CassandraMappingsSourcesDAO(cassandra.getConf()),
             new CassandraSchemaVersionManager(cassandraSchemaVersionDAO));
-
-        cassandraSchemaVersionDAO.updateVersion(SCHEMA_VERSION_V7);
-
-        return rrt;
     }
 }
diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java
index 063cb83..35246b9 100644
--- a/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/rrt/cassandra/CassandraRecipientRewriteTableV7Test.java
@@ -69,7 +69,7 @@ public class CassandraRecipientRewriteTableV7Test extends AbstractRecipientRewri
             new CassandraMappingsSourcesDAO(cassandra.getConf()),
             new CassandraSchemaVersionManager(cassandraSchemaVersionDAO));
 
-        cassandraSchemaVersionDAO.updateVersion(SCHEMA_VERSION_V7);
+        cassandraSchemaVersionDAO.updateVersion(SCHEMA_VERSION_V7).block();
 
         return rrt;
     }


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