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/03/02 03:15:57 UTC

[james-project] branch master updated (e3d4734 -> 3f13066)

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 e3d4734  JAMES-3054 Document RabbitMQ mailQueue limitations
     new 9a1d36b  MAILBOX-396 Some reactor improvement in CassandraMessageMapper
     new 683df7b  MAILBOX-396 Windowing IMAP message reads
     new 8cc581e  MAILBOX-396 CassandraMailboxMapper::findMailboxWithPathLike reactive
     new 2e92b18  MAILBOX-396 Reduce query amount upon listing message
     new 60752b1  JAMES-3061 Starting to provision cassandra testing users and keyspaces
     new 079bd02  JAMES-3061 Moving the `key space creations` duty to the DockerCassandra
     new dae26f2  JAMES-3061 KeyspaceFactory should check first then create
     new 499533a  JAMES-3061 Using the right cluster configuration
     new f743a4b  JAMES-3061 Simplify CassandraCluster resources cleanup
     new f523a3b  JAMES-3061 Created clusters should work perfectly
     new 9d9edcd  JAMES-3061 Simplify FixingGhostMailboxTest setup
     new 745a160  JAMES-3061 Rename NO_MODULE to EMPTY_MODULE in CassandraModule
     new e955652  JAMES−3074 Create UidValidity type
     new 83cacbf  JAMES-3074 Extends UidValidity strong typing in the James code base
     new cd2d2a8  JAMES-3057 MaildirFolder should not rely on an invalid UidValidity
     new 0148870  JAMES-3074 Generate valid, random based UidValidity
     new d6a921c  JAMES-3074 Tests should be using UidValidity::ofValid
     new 8553574  JAMES-3074 Warn against the usage of UidValidity::of
     new 7efbf92  JAMES-3074 s/UidValidity::random/UidValidity::generate/
     new 7b3ba54  JAMES-3075 prove that CassandraIndexTableHandler don't handle errors gracefully
     new 117f5c7  JAMES-3075 CassandraIndexTableHandler should use Flux::mergeDelayError
     new 4a68140  [REACTOR] CassandraUserMailboxRightsDAO should merge flux on updates
     new d37340b  JAMES-2985 JPAMessageMapper should also delete messages not marked as deleted
     new 2bec84c  [Refactoring] extract immediate worker from RabbitMQWorkqueueTest
     new 8e87759  JAMES-3080 add test to ensure message can survive a rabbitMQ restart
     new fba9579  JAMES-3080 add test to ensure message can survive a rabbitMQ restart
     new 7fa917f  JAMES-3080 set persistent delivery mode when submiting message to the rabbit workqueue
     new a88293a  JAMES-3080 enable workqueue persistence test
     new 3f13066  [Refactoring] removed unused fields

The 29 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:
 .../cassandra/components/CassandraModule.java      |   2 +
 .../backends/cassandra/init/ClusterFactory.java    |  19 ++
 .../backends/cassandra/init/KeyspaceFactory.java   |  42 ++-
 .../cassandra/init/ResilientClusterProvider.java   |   4 +-
 .../james/backends/cassandra/CassandraCluster.java |  51 ++-
 .../cassandra/CassandraClusterExtension.java       |  13 +-
 .../james/backends/cassandra/DockerCassandra.java  | 129 +++++++-
 .../cassandra/init/ClusterFactoryTest.java         |  60 +++-
 .../init/ResilientClusterProviderTest.java         | 145 +++++++++
 .../SessionWithInitializedTablesFactoryTest.java   |  10 +-
 .../org/apache/james/mailbox/MessageManager.java   |   3 +-
 .../org/apache/james/mailbox/model/Mailbox.java    |   6 +-
 .../apache/james/mailbox/model/UidValidity.java    | 113 +++++++
 .../james/mailbox/model/MailboxAssertingTool.java  |   2 +-
 .../mailbox/model/MailboxAssertingToolTest.java    |   9 +-
 .../james/mailbox/model/UidValidityTest.java       | 121 +++++++
 .../apache/james/mailbox/backup/zip/Zipper.java    |   2 +-
 .../mailbox/backup/MailboxMessageFixture.java      |   9 +-
 .../apache/james/mailbox/backup/ZipperTest.java    |   2 +-
 .../cassandra/mail/CassandraIndexTableHandler.java |  45 +--
 .../cassandra/mail/CassandraMailboxDAO.java        |   5 +-
 .../cassandra/mail/CassandraMailboxMapper.java     |  36 +--
 .../cassandra/mail/CassandraMessageIdMapper.java   |  20 +-
 .../cassandra/mail/CassandraMessageMapper.java     |  45 +--
 .../mail/CassandraUserMailboxRightsDAO.java        |  16 +-
 .../mail/CassandraIndexTableHandlerTest.java       |  32 +-
 .../mail/CassandraMailboxCounterDAOTest.java       |   3 +-
 .../cassandra/mail/CassandraMailboxDAOTest.java    |   5 +-
 .../CassandraMailboxMapperConcurrencyTest.java     |   3 +-
 .../cassandra/mail/CassandraMailboxMapperTest.java |   3 +-
 .../mail/CassandraModSeqProviderTest.java          |   3 +-
 .../cassandra/mail/CassandraUidProviderTest.java   |   3 +-
 .../mail/migration/MailboxPathV2MigrationTest.java |   3 +-
 .../SolveMailboxInconsistenciesServiceTest.java    |   5 +-
 ...asticSearchListeningMessageSearchIndexTest.java |   3 +-
 .../james/mailbox/jpa/mail/JPAMailboxMapper.java   |   3 +-
 .../james/mailbox/jpa/mail/JPAMessageMapper.java   |  96 +++---
 .../james/mailbox/jpa/mail/model/JPAMailbox.java   |   7 +-
 .../model/openjpa/AbstractJPAMailboxMessage.java   |   8 +-
 .../jpa/mail/TransactionalMailboxMapper.java       |   3 +-
 .../LuceneMailboxMessageSearchIndexTest.java       |   7 +-
 .../james/mailbox/maildir/MaildirFolder.java       |  32 +-
 .../mailbox/maildir/mail/MaildirMailboxMapper.java |   3 +-
 .../inmemory/mail/InMemoryMailboxMapper.java       |   3 +-
 .../InMemoryCombinationManagerTestSystem.java      |   5 +-
 .../inmemory/InMemoryMessageManagerTestSystem.java |   5 +-
 .../spamassassin/SpamAssassinListenerTest.java     |   3 +-
 .../james/mailbox/store/MailboxMetaData.java       |   9 +-
 .../james/mailbox/store/StoreMailboxManager.java   |  12 +-
 .../james/mailbox/store/StoreMessageManager.java   |   3 +-
 .../james/mailbox/store/mail/MailboxMapper.java    |   3 +-
 .../james/mailbox/store/StoreRightManagerTest.java |   3 +-
 .../store/mail/model/ListMailboxAssertTest.java    |   3 +-
 .../store/mail/model/ListMessageAssertTest.java    |   3 +-
 .../store/mail/model/MailboxMapperACLTest.java     |   3 +-
 .../store/mail/model/MailboxMapperTest.java        |   3 +-
 .../store/mail/model/MessageIdMapperTest.java      |   3 +-
 .../store/mail/model/MessageMapperTest.java        |  16 +-
 .../mailbox/store/mail/model/MessageMoveTest.java  |   3 +-
 .../model/MessageWithAttachmentMapperTest.java     |   3 +-
 .../quota/DefaultUserQuotaRootResolverTest.java    |   5 +-
 .../mailbox/store/quota/QuotaCheckerTest.java      |   3 +-
 .../CassandraRabbitMQAwsS3SmtpTestRuleFactory.java |   7 +-
 .../mpt/smtp/CassandraSmtpTestRuleFactory.java     |   7 +-
 .../imap/api/message/response/StatusResponse.java  |  13 +-
 .../parser/AbstractSelectionCommandParser.java     |   7 +-
 .../imap/decode/parser/ExamineCommandParser.java   |   3 +-
 .../imap/decode/parser/SelectCommandParser.java    |   3 +-
 .../imap/encode/MailboxStatusResponseEncoder.java  |   7 +-
 .../request/AbstractMailboxSelectionRequest.java   |   7 +-
 .../james/imap/message/request/ExamineRequest.java |   3 +-
 .../james/imap/message/request/SelectRequest.java  |   3 +-
 .../message/response/MailboxStatusResponse.java    |   7 +-
 .../processor/AbstractMessageRangeProcessor.java   |   3 +-
 .../imap/processor/AbstractSelectionProcessor.java |   7 +-
 .../james/imap/processor/AppendProcessor.java      |   3 +-
 .../james/imap/processor/ExamineProcessor.java     |   5 +-
 .../james/imap/processor/SelectProcessor.java      |   5 +-
 .../james/imap/processor/StatusProcessor.java      |   5 +-
 .../encode/MailboxStatusResponseEncoderTest.java   |   3 +-
 .../james/imap/processor/CopyProcessorTest.java    |   6 +-
 .../james/imap/processor/MoveProcessorTest.java    |   6 +-
 .../processor/base/MailboxEventAnalyserTest.java   |   3 +-
 .../org/apache/james/server/CassandraProbe.java    |   4 +-
 .../AuthenticatedCassandraJamesServerTest.java     |  34 +-
 .../james/CassandraAuthenticationExtension.java    |  75 -----
 .../java/org/apache/james/CassandraExtension.java  |  24 --
 .../org/apache/james/CassandraNodeConfTest.java    |  24 +-
 .../java/org/apache/james/DockerCassandraRule.java |   7 +-
 .../adapter/mailbox/MailboxManagementTest.java     |   3 +-
 ...ventSourcingDLPConfigurationStoreExtension.java |  22 +-
 .../cassandra/CassandraDomainListTest.java         |   3 +-
 .../CassandraRecipientRewriteTableV6Test.java      |   3 +-
 .../CassandraRecipientRewriteTableV7Test.java      |   3 +-
 .../cassandra/CassandraSieveRepositoryTest.java    |   3 +-
 .../access/CassandraAccessTokenRepositoryTest.java |   3 +-
 .../CassandraNotificationRegistryTest.java         |   3 +-
 .../vacation/CassandraVacationRepositoryTest.java  |   3 +-
 .../james/pop3server/mailbox/MailboxAdapter.java   | 349 +++++++++++----------
 .../rabbitmq/FixingGhostMailboxTest.java           |  23 +-
 .../distributed/RabbitMQWorkQueue.java             |  18 +-
 .../distributed/ImmediateWorker.java}              |  54 ++--
 .../RabbitMQWorkQueuePersistenceTest.java          | 107 +++++++
 .../distributed/RabbitMQWorkQueueTest.java         |  36 ---
 104 files changed, 1385 insertions(+), 751 deletions(-)
 create mode 100644 backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java
 create mode 100644 mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
 create mode 100644 mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java
 delete mode 100644 server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraAuthenticationExtension.java
 copy server/task/{task-memory/src/main/java/org/apache/james/task/MemoryWorkQueue.java => task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/ImmediateWorker.java} (54%)
 create mode 100644 server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueuePersistenceTest.java


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


[james-project] 03/29: MAILBOX-396 CassandraMailboxMapper::findMailboxWithPathLike reactive

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 8cc581e69d8ae2158d4ae94d31559abb10b0c505
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Feb 26 09:14:06 2020 +0700

    MAILBOX-396 CassandraMailboxMapper::findMailboxWithPathLike reactive
    
    We can:
     - Avoid calling two time block in a sequential manner
     - We can avoid fetching mailbox details and ACLs for entries already
     migrated to V2
---
 .../cassandra/mail/CassandraMailboxMapper.java     | 33 +++++++---------------
 1 file changed, 10 insertions(+), 23 deletions(-)

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 1c549db..bfeb59f 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
@@ -42,9 +42,7 @@ import org.apache.james.util.ReactorUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.github.steveash.guavate.Guavate;
 import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
 
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
@@ -137,27 +135,16 @@ public class CassandraMailboxMapper implements MailboxMapper {
 
     @Override
     public List<Mailbox> findMailboxWithPathLike(MailboxQuery.UserBound query) {
-        List<Mailbox> mailboxesV2 = toMailboxes(query, mailboxPathV2DAO.listUserMailboxes(query.getFixedNamespace(), query.getFixedUser()));
-        List<Mailbox> mailboxesV1 = toMailboxes(query, mailboxPathDAO.listUserMailboxes(query.getFixedNamespace(), query.getFixedUser()));
-
-        List<Mailbox> mailboxesV1NotInV2 = mailboxesV1.stream()
-            .filter(mailboxV1 -> mailboxesV2.stream()
-                .map(Mailbox::generateAssociatedPath)
-                .noneMatch(mailboxV2path -> mailboxV2path.equals(mailboxV1.generateAssociatedPath())))
-            .collect(Guavate.toImmutableList());
-
-        return ImmutableList.<Mailbox>builder()
-            .addAll(mailboxesV2)
-            .addAll(mailboxesV1NotInV2)
-            .build();
-    }
-
-    private List<Mailbox> toMailboxes(MailboxQuery.UserBound query, Flux<CassandraIdAndPath> listUserMailboxes) {
-        return listUserMailboxes
-                .filter(idAndPath -> query.isPathMatch(idAndPath.getMailboxPath()))
-                .concatMap(this::retrieveMailbox)
-                .collectList()
-                .block();
+        String fixedNamespace = query.getFixedNamespace();
+        Username fixedUser = query.getFixedUser();
+
+        return Flux.concat(mailboxPathV2DAO.listUserMailboxes(fixedNamespace, fixedUser),
+                mailboxPathDAO.listUserMailboxes(fixedNamespace, fixedUser))
+            .filter(idAndPath -> query.isPathMatch(idAndPath.getMailboxPath()))
+            .distinct(CassandraIdAndPath::getMailboxPath)
+            .concatMap(this::retrieveMailbox)
+            .collectList()
+            .block();
     }
 
     private Mono<Mailbox> retrieveMailbox(CassandraIdAndPath idAndPath) {


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


[james-project] 10/29: JAMES-3061 Created clusters should work perfectly

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 f523a3b53d3ab7f009b6a8d6bcba44c54ffbd1db
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Tue Feb 25 10:58:46 2020 +0700

    JAMES-3061 Created clusters should work perfectly
---
 .../backends/cassandra/init/ClusterFactory.java    | 19 +++++++
 .../james/backends/cassandra/DockerCassandra.java  | 15 ++++--
 .../cassandra/init/ClusterFactoryTest.java         | 60 +++++++++++++++++++---
 .../init/ResilientClusterProviderTest.java         |  8 +--
 4 files changed, 87 insertions(+), 15 deletions(-)

diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ClusterFactory.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ClusterFactory.java
index ff04fb4..a6bfc9e 100644
--- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ClusterFactory.java
+++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ClusterFactory.java
@@ -19,15 +19,20 @@
 
 package org.apache.james.backends.cassandra.init;
 
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+
 import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 
+import com.datastax.driver.core.BoundStatement;
 import com.datastax.driver.core.Cluster;
 import com.datastax.driver.core.ConsistencyLevel;
 import com.datastax.driver.core.QueryOptions;
+import com.datastax.driver.core.Session;
 import com.datastax.driver.core.SocketOptions;
 import com.google.common.base.Preconditions;
 
 public class ClusterFactory {
+
     public static Cluster create(ClusterConfiguration configuration) {
         Preconditions.checkState(configuration.getUsername().isPresent() == configuration.getPassword().isPresent(), "If you specify username, you must specify password");
 
@@ -57,6 +62,7 @@ public class ClusterFactory {
         try {
             configuration.getQueryLoggerConfiguration().map(queryLoggerConfiguration ->
                 cluster.register(queryLoggerConfiguration.getQueryLogger()));
+            ensureContactable(cluster);
             return cluster;
         } catch (Exception e) {
             cluster.close();
@@ -68,4 +74,17 @@ public class ClusterFactory {
         return new QueryOptions()
                 .setConsistencyLevel(ConsistencyLevel.QUORUM);
     }
+
+    private static void ensureContactable(Cluster cluster) {
+        try (Session session = cluster.connect("system")) {
+            session.execute(checkConnectionStatement(session));
+        }
+    }
+
+    private static BoundStatement checkConnectionStatement(Session session) {
+        return session.prepare(select()
+                .fcall("NOW")
+                .from("local"))
+            .bind();
+    }
 }
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java
index dc1122c..b4db209 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java
@@ -63,7 +63,7 @@ public class DockerCassandra {
             try (Cluster privilegedCluster = ClusterFactory.create(configuration)) {
                 provisionNonPrivilegedUser(privilegedCluster);
                 KeyspaceFactory.createKeyspace(configuration, privilegedCluster);
-                grantPermissionTestingUser(privilegedCluster, keyspace);
+                grantPermissionToTestingUser(privilegedCluster, keyspace);
             }
         }
 
@@ -95,7 +95,7 @@ public class DockerCassandra {
             }
         }
 
-        private void grantPermissionTestingUser(Cluster privilegedCluster, String keyspace) {
+        private void grantPermissionToTestingUser(Cluster privilegedCluster, String keyspace) {
             try (Session session = privilegedCluster.newSession()) {
                 session.execute("GRANT CREATE ON KEYSPACE " + keyspace + " TO " + CASSANDRA_TESTING_USER);
                 session.execute("GRANT SELECT ON KEYSPACE " + keyspace + " TO " + CASSANDRA_TESTING_USER);
@@ -223,7 +223,16 @@ public class DockerCassandra {
     }
 
     public void unpause() {
-        client.unpauseContainerCmd(cassandraContainer.getContainerId()).exec();
+        if (isPaused()) {
+            client.unpauseContainerCmd(cassandraContainer.getContainerId()).exec();
+        }
+    }
+
+    private boolean isPaused() {
+        return client.inspectContainerCmd(cassandraContainer.getContainerId())
+            .exec()
+            .getState()
+            .getPaused();
     }
 
     public ClusterConfiguration.Builder configurationBuilder() {
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ClusterFactoryTest.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ClusterFactoryTest.java
index ce45523..75698f8 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ClusterFactoryTest.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ClusterFactoryTest.java
@@ -18,27 +18,71 @@
  ****************************************************************/
 package org.apache.james.backends.cassandra.init;
 
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
-import org.apache.james.util.Host;
+import org.apache.james.backends.cassandra.CassandraClusterExtension;
+import org.apache.james.backends.cassandra.DockerCassandra;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 
 import com.datastax.driver.core.Cluster;
 import com.datastax.driver.core.ConsistencyLevel;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.exceptions.NoHostAvailableException;
 
 class ClusterFactoryTest {
 
+    @RegisterExtension
+    static CassandraClusterExtension cassandraExtension = new CassandraClusterExtension(CassandraModule.NO_MODULE);
+
+    @AfterEach
+    void tearDown(DockerCassandra dockerCassandra) {
+        dockerCassandra.unpause();
+    }
+
     @Test
-    void consistencyLevelShouldBeEqualToQuorum() {
-        Cluster cluster = ClusterFactory.create(ClusterConfiguration.builder()
-                .host(Host.from("localhost", ClusterConfiguration.DEFAULT_CASSANDRA_PORT))
-                .build());
+    void consistencyLevelShouldBeEqualToQuorum(DockerCassandra dockerCassandra) {
+        Cluster cluster = ClusterFactory.create(dockerCassandra.configurationBuilder()
+            .build());
 
         ConsistencyLevel consistencyLevel = cluster.getConfiguration()
-                .getQueryOptions()
-                .getConsistencyLevel();
+            .getQueryOptions()
+            .getConsistencyLevel();
 
         assertThat(consistencyLevel).isEqualTo(ConsistencyLevel.QUORUM);
     }
+
+    @Test
+    void createShouldThrowWhenContactableCluster(DockerCassandra dockerCassandra) {
+        dockerCassandra.pause();
+
+        assertThatThrownBy(() -> ClusterFactory.create(
+            dockerCassandra.configurationBuilder()
+                .build()))
+            .isInstanceOf(NoHostAvailableException.class);
+    }
+
+    @Test
+    void createShouldReturnAContactableCluster(DockerCassandra dockerCassandra) {
+        Cluster cluster = ClusterFactory.create(dockerCassandra.configurationBuilder()
+            .build());
+
+        assertThatClusterIsContactable(cluster);
+    }
+
+    void assertThatClusterIsContactable(Cluster cluster) {
+        try (Session session = cluster.connect("system")) {
+            session.execute(
+                session.prepare(select()
+                    .fcall("NOW")
+                    .from("local"))
+                .bind());
+        } catch (Exception e) {
+            throw new AssertionError("expecting cluster can be connected but actually not", e);
+        }
+    }
 }
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java
index 357eb7c..f4493c6 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java
@@ -72,7 +72,7 @@ class ResilientClusterProviderTest {
         }
 
         @Test
-        void initializationShouldNotThrownWhenKeyspaceAlreadyExisted(DockerCassandra dockerCassandra) {
+        void initializationShouldNotThrowWhenKeyspaceAlreadyExisted(DockerCassandra dockerCassandra) {
             ClusterConfiguration configuration = dockerCassandra.configurationBuilder()
                 .keyspace(KEYSPACE)
                 .createKeyspace()
@@ -85,7 +85,7 @@ class ResilientClusterProviderTest {
         }
 
         @Test
-        void initializationShouldNotImpactToKeyspaceExistentWhenAlreadyExisted(DockerCassandra dockerCassandra) {
+        void initializationShouldNotImpactKeyspaceExistenceWhenItAlreadyExisted(DockerCassandra dockerCassandra) {
             ClusterConfiguration configuration = dockerCassandra.configurationBuilder()
                 .keyspace(KEYSPACE)
                 .createKeyspace()
@@ -116,7 +116,7 @@ class ResilientClusterProviderTest {
         }
 
         @Test
-        void initializationShouldNotThrownWhenKeyspaceAlreadyExisted(DockerCassandra dockerCassandra) {
+        void initializationShouldNotThrowWhenKeyspaceAlreadyExisted(DockerCassandra dockerCassandra) {
             ClusterConfiguration configuration = dockerCassandra.configurationBuilder()
                 .keyspace(KEYSPACE)
                 .build();
@@ -128,7 +128,7 @@ class ResilientClusterProviderTest {
         }
 
         @Test
-        void initializationShouldNotImpactToKeyspaceExistentWhenAlreadyExisted(DockerCassandra dockerCassandra) {
+        void initializationShouldNotImpactKeyspaceExistenceWhenItAlreadyExisted(DockerCassandra dockerCassandra) {
             ClusterConfiguration configuration = dockerCassandra.configurationBuilder()
                 .keyspace(KEYSPACE)
                 .build();


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


[james-project] 21/29: JAMES-3075 CassandraIndexTableHandler should use Flux::mergeDelayError

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 117f5c79df61ee7023766eaec09556d649e8c310
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Feb 27 15:19:40 2020 +0700

    JAMES-3075 CassandraIndexTableHandler should use Flux::mergeDelayError
---
 .../cassandra/mail/CassandraIndexTableHandler.java | 45 +++++++++++-----------
 .../mail/CassandraIndexTableHandlerTest.java       |  2 -
 2 files changed, 23 insertions(+), 24 deletions(-)

diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandler.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandler.java
index 84516fa..2232234 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandler.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandler.java
@@ -32,6 +32,7 @@ import com.google.common.collect.ImmutableSet;
 
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
+import reactor.util.concurrent.Queues;
 
 public class CassandraIndexTableHandler {
 
@@ -57,36 +58,36 @@ public class CassandraIndexTableHandler {
     public Mono<Void> updateIndexOnDelete(ComposedMessageIdWithMetaData composedMessageIdWithMetaData, CassandraId mailboxId) {
         MessageUid uid = composedMessageIdWithMetaData.getComposedMessageId().getUid();
 
-        return Flux.merge(
-               updateFirstUnseenOnDelete(mailboxId, composedMessageIdWithMetaData.getFlags(), composedMessageIdWithMetaData.getComposedMessageId().getUid()),
-               mailboxRecentDAO.removeFromRecent(mailboxId, composedMessageIdWithMetaData.getComposedMessageId().getUid()),
-               mailboxCounterDAO.decrementCount(mailboxId),
-               deletedMessageDAO.removeDeleted(mailboxId, uid),
-               decrementUnseenOnDelete(mailboxId, composedMessageIdWithMetaData.getFlags()))
-                .then();
+        return Flux.mergeDelayError(Queues.XS_BUFFER_SIZE,
+                updateFirstUnseenOnDelete(mailboxId, composedMessageIdWithMetaData.getFlags(), composedMessageIdWithMetaData.getComposedMessageId().getUid()),
+                mailboxRecentDAO.removeFromRecent(mailboxId, composedMessageIdWithMetaData.getComposedMessageId().getUid()),
+                mailboxCounterDAO.decrementCount(mailboxId),
+                deletedMessageDAO.removeDeleted(mailboxId, uid),
+                decrementUnseenOnDelete(mailboxId, composedMessageIdWithMetaData.getFlags()))
+            .then();
     }
 
     public Mono<Void> updateIndexOnAdd(MailboxMessage message, CassandraId mailboxId) {
         Flags flags = message.createFlags();
 
-        return Flux.merge(
-               checkDeletedOnAdd(mailboxId, message.createFlags(), message.getUid()),
-               updateFirstUnseenOnAdd(mailboxId, message.createFlags(), message.getUid()),
-               addRecentOnSave(mailboxId, message),
-               incrementUnseenOnSave(mailboxId, flags),
-               mailboxCounterDAO.incrementCount(mailboxId),
-               applicableFlagDAO.updateApplicableFlags(mailboxId, ImmutableSet.copyOf(flags.getUserFlags())))
-                .then();
+        return Flux.mergeDelayError(Queues.XS_BUFFER_SIZE,
+                checkDeletedOnAdd(mailboxId, message.createFlags(), message.getUid()),
+                updateFirstUnseenOnAdd(mailboxId, message.createFlags(), message.getUid()),
+                addRecentOnSave(mailboxId, message),
+                incrementUnseenOnSave(mailboxId, flags),
+                mailboxCounterDAO.incrementCount(mailboxId),
+                applicableFlagDAO.updateApplicableFlags(mailboxId, ImmutableSet.copyOf(flags.getUserFlags())))
+            .then();
     }
 
     public Mono<Void> updateIndexOnFlagsUpdate(CassandraId mailboxId, UpdatedFlags updatedFlags) {
-        return Flux.merge(
-               manageUnseenMessageCountsOnFlagsUpdate(mailboxId, updatedFlags),
-               manageRecentOnFlagsUpdate(mailboxId, updatedFlags),
-               updateFirstUnseenOnFlagsUpdate(mailboxId, updatedFlags),
-               applicableFlagDAO.updateApplicableFlags(mailboxId, ImmutableSet.copyOf(updatedFlags.userFlagIterator())),
-               updateDeletedOnFlagsUpdate(mailboxId, updatedFlags))
-                .then();
+        return Flux.mergeDelayError(Queues.XS_BUFFER_SIZE,
+                manageUnseenMessageCountsOnFlagsUpdate(mailboxId, updatedFlags),
+                manageRecentOnFlagsUpdate(mailboxId, updatedFlags),
+                updateFirstUnseenOnFlagsUpdate(mailboxId, updatedFlags),
+                applicableFlagDAO.updateApplicableFlags(mailboxId, ImmutableSet.copyOf(updatedFlags.userFlagIterator())),
+                updateDeletedOnFlagsUpdate(mailboxId, updatedFlags))
+            .then();
     }
 
     private Mono<Void> updateDeletedOnFlagsUpdate(CassandraId mailboxId, UpdatedFlags updatedFlags) {
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
index 6259819..4ba6fbb 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
@@ -50,7 +50,6 @@ import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.store.MessageBuilder;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
@@ -103,7 +102,6 @@ class CassandraIndexTableHandlerTest {
 
     @Nested
     class Failures {
-        @Disabled("JAMES-3075 prove that CassandraIndexTableHandler don't handle errors gracefully")
         @Test
         void messageCountShouldBeUpdatedUponDeletedMessageFailure(CassandraCluster cassandra) throws Exception {
             MailboxMessage message = new MessageBuilder()


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


[james-project] 07/29: JAMES-3061 KeyspaceFactory should check first then create

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 dae26f2e50357b54a49fcf6292273152e33faa17
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Mon Feb 24 18:15:19 2020 +0700

    JAMES-3061 KeyspaceFactory should check first then create
    
    Rather than using `create if not exist`. It causes a non authorized
    exceptions on non privileged users even with the `not exist`
---
 .../cassandra/components/CassandraModule.java      |   2 +
 .../backends/cassandra/init/KeyspaceFactory.java   |  42 +++++-
 .../cassandra/init/ResilientClusterProvider.java   |   4 +-
 .../cassandra/CassandraClusterExtension.java       |  13 +-
 .../init/ResilientClusterProviderTest.java         | 145 +++++++++++++++++++++
 5 files changed, 196 insertions(+), 10 deletions(-)

diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/components/CassandraModule.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/components/CassandraModule.java
index 252b6f9..9ea8665 100644
--- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/components/CassandraModule.java
+++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/components/CassandraModule.java
@@ -185,6 +185,8 @@ public interface CassandraModule {
             .build();
     }
 
+    CassandraModule NO_MODULE = builder().build();
+
     List<CassandraTable> moduleTables();
 
     List<CassandraType> moduleTypes();
diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/KeyspaceFactory.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/KeyspaceFactory.java
index be1630b..ce6a227 100644
--- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/KeyspaceFactory.java
+++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/KeyspaceFactory.java
@@ -19,12 +19,23 @@
 
 package org.apache.james.backends.cassandra.init;
 
+import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;
+import static com.datastax.driver.core.querybuilder.QueryBuilder.select;
+
 import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 
 import com.datastax.driver.core.Cluster;
 import com.datastax.driver.core.Session;
+import com.datastax.driver.core.schemabuilder.SchemaBuilder;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
 
 public class KeyspaceFactory {
+
+    private static final String SYSTEM_SCHEMA = "system_schema";
+    private static final String KEYSPACES = "keyspaces";
+    private static final String KEYSPACE_NAME = "keyspace_name";
+
     public static void createKeyspace(ClusterConfiguration clusterConfiguration, Cluster cluster) {
         if (clusterConfiguration.shouldCreateKeyspace()) {
             doCreateKeyspace(clusterConfiguration, cluster);
@@ -33,10 +44,33 @@ public class KeyspaceFactory {
 
     private static void doCreateKeyspace(ClusterConfiguration clusterConfiguration, Cluster cluster) {
         try (Session session = cluster.connect()) {
-            session.execute("CREATE KEYSPACE IF NOT EXISTS " + clusterConfiguration.getKeyspace()
-                + " WITH replication = {'class':'SimpleStrategy', 'replication_factor':" + clusterConfiguration.getReplicationFactor() + "}"
-                + " AND durable_writes = " + clusterConfiguration.isDurableWrites()
-                + ";");
+            if (!keyspaceExist(cluster, clusterConfiguration.getKeyspace())) {
+                session.execute(SchemaBuilder.createKeyspace(clusterConfiguration.getKeyspace())
+                    .with()
+                    .replication(ImmutableMap.<String, Object>builder()
+                        .put("class", "SimpleStrategy")
+                        .put("replication_factor", clusterConfiguration.getReplicationFactor())
+                        .build())
+                    .durableWrites(clusterConfiguration.isDurableWrites()));
+            }
+        }
+    }
+
+    @VisibleForTesting
+    public static boolean keyspaceExist(Cluster cluster, String keyspaceName) {
+        try (Session session = cluster.connect(SYSTEM_SCHEMA)) {
+            long numberOfKeyspaces = session.execute(select()
+                    .countAll()
+                    .from(KEYSPACES)
+                    .where(eq(KEYSPACE_NAME, keyspaceName)))
+                .one()
+                .getLong("count");
+
+            if (numberOfKeyspaces > 1 || numberOfKeyspaces < 0) {
+                throw new IllegalStateException(String.format("unexpected keyspace('%s') count being %d", keyspaceName, numberOfKeyspaces));
+            }
+
+            return numberOfKeyspaces == 1;
         }
     }
 }
diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ResilientClusterProvider.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ResilientClusterProvider.java
index 01040bb..5b823bf 100644
--- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ResilientClusterProvider.java
+++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ResilientClusterProvider.java
@@ -33,6 +33,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.datastax.driver.core.Cluster;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 
 import reactor.core.publisher.Mono;
@@ -44,8 +45,9 @@ public class ResilientClusterProvider implements Provider<Cluster> {
 
     private final Cluster cluster;
 
+    @VisibleForTesting
     @Inject
-    private ResilientClusterProvider(ClusterConfiguration configuration) {
+    ResilientClusterProvider(ClusterConfiguration configuration) {
         Duration waitDelay = Duration.ofMillis(configuration.getMinDelay());
         Duration forever = Duration.ofMillis(Long.MAX_VALUE);
         cluster = Mono.fromCallable(getClusterRetryCallable(configuration))
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraClusterExtension.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraClusterExtension.java
index 5eb5599..35fc63a 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraClusterExtension.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraClusterExtension.java
@@ -76,17 +76,20 @@ public class CassandraClusterExtension implements BeforeAllCallback, BeforeEachC
 
     @Override
     public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
-        return parameterContext.getParameter().getType() == CassandraCluster.class
-            || parameterContext.getParameter().getType() == DockerCassandra.class;
+        Class<?> paramType = parameterContext.getParameter().getType();
+        return paramType.isAssignableFrom(CassandraCluster.class)
+            || paramType.isAssignableFrom(DockerCassandra.class);
     }
 
     @Override
     public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
-        if (parameterContext.getParameter().getType() == CassandraCluster.class) {
+        Class<?> paramType = parameterContext.getParameter().getType();
+        if (paramType.isAssignableFrom(CassandraCluster.class)) {
             return cassandraCluster;
+        } else if (paramType.isAssignableFrom(DockerCassandra.class)) {
+            return DockerCassandraSingleton.singleton;
         }
-
-        return DockerCassandraSingleton.singleton;
+        throw new IllegalArgumentException("Unsupported parameter type " + paramType.getName());
     }
 
     public CassandraCluster getCassandraCluster() {
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java
new file mode 100644
index 0000000..357eb7c
--- /dev/null
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java
@@ -0,0 +1,145 @@
+/****************************************************************
+ * 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.backends.cassandra.init;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.james.backends.cassandra.CassandraClusterExtension;
+import org.apache.james.backends.cassandra.DockerCassandra;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class ResilientClusterProviderTest {
+
+    private static final String KEYSPACE = "my_keyspace";
+
+    @RegisterExtension
+    static CassandraClusterExtension cassandraExtension = new CassandraClusterExtension(CassandraModule.NO_MODULE);
+
+    @AfterEach
+    void tearDown(DockerCassandra dockerCassandra) {
+        dockerCassandra.administrator()
+            .dropKeyspace(KEYSPACE);
+    }
+
+    @Nested
+    class WhenAllowCreatingKeySpace {
+
+        @Test
+        void initializationShouldThrowWhenKeyspaceDoesntExist(DockerCassandra dockerCassandra) {
+            assertThatThrownBy(() -> new ResilientClusterProvider(
+                    dockerCassandra.configurationBuilder()
+                        .keyspace(KEYSPACE)
+                        .createKeyspace()
+                        .build()))
+                .isInstanceOf(IllegalStateException.class)
+                .hasStackTraceContaining("User james_testing has no CREATE permission on <all keyspaces> or any of its parents");
+        }
+
+        @Test
+        void initializationWithPrivilegedUserShouldCreateKeySpaceWhenNotExisted(DockerCassandra dockerCassandra) {
+            new ResilientClusterProvider(dockerCassandra.configurationBuilderForSuperUser()
+                .keyspace(KEYSPACE)
+                .createKeyspace()
+                .build());
+
+            assertThat(dockerCassandra.administrator()
+                    .keyspaceExist(KEYSPACE))
+                .isTrue();
+        }
+
+        @Test
+        void initializationShouldNotThrownWhenKeyspaceAlreadyExisted(DockerCassandra dockerCassandra) {
+            ClusterConfiguration configuration = dockerCassandra.configurationBuilder()
+                .keyspace(KEYSPACE)
+                .createKeyspace()
+                .build();
+            dockerCassandra.administrator()
+                .initializeKeyspace(KEYSPACE);
+
+            assertThatCode(() -> new ResilientClusterProvider(configuration))
+                .doesNotThrowAnyException();
+        }
+
+        @Test
+        void initializationShouldNotImpactToKeyspaceExistentWhenAlreadyExisted(DockerCassandra dockerCassandra) {
+            ClusterConfiguration configuration = dockerCassandra.configurationBuilder()
+                .keyspace(KEYSPACE)
+                .createKeyspace()
+                .build();
+            dockerCassandra.administrator()
+                .initializeKeyspace(KEYSPACE);
+
+            new ResilientClusterProvider(configuration);
+
+            assertThat(dockerCassandra.administrator()
+                    .keyspaceExist(KEYSPACE))
+                .isTrue();
+        }
+    }
+
+    @Nested
+    class WhenProhibitCreatingKeySpace {
+
+        @Test
+        void initializationShouldNotCreateWhenKeyspaceDoesntExist(DockerCassandra dockerCassandra) {
+            new ResilientClusterProvider(dockerCassandra.configurationBuilder()
+                .keyspace(KEYSPACE)
+                .build());
+
+            assertThat(dockerCassandra.administrator()
+                    .keyspaceExist(KEYSPACE))
+                .isFalse();
+        }
+
+        @Test
+        void initializationShouldNotThrownWhenKeyspaceAlreadyExisted(DockerCassandra dockerCassandra) {
+            ClusterConfiguration configuration = dockerCassandra.configurationBuilder()
+                .keyspace(KEYSPACE)
+                .build();
+            dockerCassandra.administrator()
+                .initializeKeyspace(KEYSPACE);
+
+            assertThatCode(() -> new ResilientClusterProvider(configuration))
+                .doesNotThrowAnyException();
+        }
+
+        @Test
+        void initializationShouldNotImpactToKeyspaceExistentWhenAlreadyExisted(DockerCassandra dockerCassandra) {
+            ClusterConfiguration configuration = dockerCassandra.configurationBuilder()
+                .keyspace(KEYSPACE)
+                .build();
+            dockerCassandra.administrator()
+                .initializeKeyspace(KEYSPACE);
+
+            new ResilientClusterProvider(configuration);
+
+            assertThat(dockerCassandra.administrator()
+                    .keyspaceExist(KEYSPACE))
+                .isTrue();
+        }
+    }
+}
\ No newline at end of file


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


[james-project] 02/29: MAILBOX-396 Windowing IMAP message reads

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 683df7b9bfd43afe2b51ce19ef200ca6fccbb924
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Feb 10 10:55:52 2020 +0700

    MAILBOX-396 Windowing IMAP message reads
    
    This can prevent us from putting undue pressure on Cassandra upon IMAP
    large range message operations
---
 .../james/mailbox/cassandra/mail/CassandraMessageMapper.java       | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 7fc68f1..6f4b7df 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -172,16 +172,17 @@ public class CassandraMessageMapper implements MessageMapper {
     public Iterator<MailboxMessage> findInMailbox(Mailbox mailbox, MessageRange messageRange, FetchType ftype, int max) {
         CassandraId mailboxId = (CassandraId) mailbox.getMailboxId();
         return retrieveMessageIds(mailboxId, messageRange)
-            .flatMapMany(ids -> retrieveMessages(ids, ftype, Limit.from(max)))
+            .flatMap(ids -> retrieveMessages(ids, ftype, Limit.from(max)))
             .map(MailboxMessage.class::cast)
             .sort(Comparator.comparing(MailboxMessage::getUid))
             .toIterable()
             .iterator();
     }
 
-    private Mono<List<ComposedMessageIdWithMetaData>> retrieveMessageIds(CassandraId mailboxId, MessageRange messageRange) {
+    private Flux<List<ComposedMessageIdWithMetaData>> retrieveMessageIds(CassandraId mailboxId, MessageRange messageRange) {
         return messageIdDAO.retrieveMessages(mailboxId, messageRange)
-            .collect(Guavate.toImmutableList());
+            .window(cassandraConfiguration.getMessageReadChunkSize())
+            .flatMap(flux -> flux.collect(Guavate.toImmutableList()));
     }
 
     private Flux<MailboxMessage> retrieveMessages(List<ComposedMessageIdWithMetaData> messageIds, FetchType fetchType, Limit limit) {


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


[james-project] 28/29: JAMES-3080 enable workqueue persistence test

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 a88293a82455ae7cbb6c7e3e1fe068b9ac64f09c
Author: Rémi KOWALSKI <rk...@linagora.com>
AuthorDate: Fri Feb 28 16:30:01 2020 +0100

    JAMES-3080 enable workqueue persistence test
---
 .../eventsourcing/distributed/RabbitMQWorkQueuePersistenceTest.java     | 2 --
 1 file changed, 2 deletions(-)

diff --git a/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueuePersistenceTest.java b/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueuePersistenceTest.java
index b83bf6f..7040957 100644
--- a/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueuePersistenceTest.java
+++ b/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueuePersistenceTest.java
@@ -35,7 +35,6 @@ import org.apache.james.task.TaskId;
 import org.apache.james.task.TaskWithId;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
@@ -70,7 +69,6 @@ class RabbitMQWorkQueuePersistenceTest {
      * start a workqueue which consume messages
      * verify that the message is treated
      */
-    @Disabled("JAMES-3080 rabbitMQ messages need to be persisted")
     @Test
     void submittedMessageShouldSurviveRabbitMQRestart() throws Exception {
         Task TASK = new MemoryReferenceTask(() -> Task.Result.COMPLETED);


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


[james-project] 08/29: JAMES-3061 Using the right cluster configuration

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 499533a0f38a32361f6351b7dd2f466786dbcbbd
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Mon Feb 24 18:17:06 2020 +0700

    JAMES-3061 Using the right cluster configuration
---
 .../SessionWithInitializedTablesFactoryTest.java   | 10 +--
 .../CassandraRabbitMQAwsS3SmtpTestRuleFactory.java |  7 +-
 .../mpt/smtp/CassandraSmtpTestRuleFactory.java     |  7 +-
 .../AuthenticatedCassandraJamesServerTest.java     | 34 ++++++----
 .../james/CassandraAuthenticationExtension.java    | 75 ----------------------
 .../org/apache/james/CassandraNodeConfTest.java    | 24 +++----
 .../java/org/apache/james/DockerCassandraRule.java |  7 +-
 7 files changed, 39 insertions(+), 125 deletions(-)

diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/SessionWithInitializedTablesFactoryTest.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/SessionWithInitializedTablesFactoryTest.java
index fb557e2..3c3345f 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/SessionWithInitializedTablesFactoryTest.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/SessionWithInitializedTablesFactoryTest.java
@@ -20,13 +20,13 @@
 package org.apache.james.backends.cassandra.init;
 
 import static com.datastax.driver.core.DataType.text;
-import static org.apache.james.backends.cassandra.CassandraCluster.KEYSPACE;
 import static org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager.MAX_VERSION;
 import static org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager.MIN_VERSION;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.util.function.Supplier;
 
+import org.apache.james.backends.cassandra.DockerCassandra;
 import org.apache.james.backends.cassandra.DockerCassandraExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
@@ -120,15 +120,9 @@ class SessionWithInitializedTablesFactoryTest {
     }
 
     private static Supplier<Session> createSession(DockerCassandraExtension.DockerCassandra cassandraServer) {
-        ClusterConfiguration clusterConfiguration = ClusterConfiguration.builder()
-            .host(cassandraServer.getHost())
-            .keyspace(KEYSPACE)
-            .createKeyspace()
-            .replicationFactor(1)
-            .disableDurableWrites()
+        ClusterConfiguration clusterConfiguration = DockerCassandra.configurationBuilder(cassandraServer.getHost())
             .build();
         Cluster cluster = ClusterFactory.create(clusterConfiguration);
-        KeyspaceFactory.createKeyspace(clusterConfiguration, cluster);
         return () -> new SessionWithInitializedTablesFactory(
                 clusterConfiguration,
                 cluster,
diff --git a/mpt/impl/smtp/cassandra-rabbitmq-object-storage/src/test/java/org/apache/james/mpt/smtp/CassandraRabbitMQAwsS3SmtpTestRuleFactory.java b/mpt/impl/smtp/cassandra-rabbitmq-object-storage/src/test/java/org/apache/james/mpt/smtp/CassandraRabbitMQAwsS3SmtpTestRuleFactory.java
index d320e63..fe02a02 100644
--- a/mpt/impl/smtp/cassandra-rabbitmq-object-storage/src/test/java/org/apache/james/mpt/smtp/CassandraRabbitMQAwsS3SmtpTestRuleFactory.java
+++ b/mpt/impl/smtp/cassandra-rabbitmq-object-storage/src/test/java/org/apache/james/mpt/smtp/CassandraRabbitMQAwsS3SmtpTestRuleFactory.java
@@ -22,6 +22,7 @@ import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
 import org.apache.james.CassandraJamesServerMain;
 import org.apache.james.CleanupTasksPerformer;
 import org.apache.james.GuiceJamesServer;
+import org.apache.james.backends.cassandra.DockerCassandra;
 import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 import org.apache.james.backends.rabbitmq.DockerRabbitMQSingleton;
 import org.apache.james.dnsservice.api.DNSService;
@@ -64,11 +65,7 @@ public final class CassandraRabbitMQAwsS3SmtpTestRuleFactory {
                 new TestRabbitMQModule(DockerRabbitMQSingleton.SINGLETON),
                 new TestAwsS3BlobStoreModule(awsS3TestRule),
                 binder -> binder.bind(ClusterConfiguration.class).toInstance(
-                    ClusterConfiguration.builder()
-                        .host(cassandraHost)
-                        .keyspace("testing")
-                        .createKeyspace()
-                        .replicationFactor(1)
+                    DockerCassandra.configurationBuilder(cassandraHost)
                         .build()),
                 binder -> binder.bind(DNSService.class).toInstance(dnsService),
                 binder -> binder.bind(CleanupTasksPerformer.class).asEagerSingleton());
diff --git a/mpt/impl/smtp/cassandra/src/test/java/org/apache/james/mpt/smtp/CassandraSmtpTestRuleFactory.java b/mpt/impl/smtp/cassandra/src/test/java/org/apache/james/mpt/smtp/CassandraSmtpTestRuleFactory.java
index 322bca0..e8d85c8 100644
--- a/mpt/impl/smtp/cassandra/src/test/java/org/apache/james/mpt/smtp/CassandraSmtpTestRuleFactory.java
+++ b/mpt/impl/smtp/cassandra/src/test/java/org/apache/james/mpt/smtp/CassandraSmtpTestRuleFactory.java
@@ -21,6 +21,7 @@ package org.apache.james.mpt.smtp;
 import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
 import org.apache.james.CassandraJamesServerMain;
 import org.apache.james.GuiceJamesServer;
+import org.apache.james.backends.cassandra.DockerCassandra;
 import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.modules.protocols.SmtpGuiceProbe.SmtpServerConnectedType;
@@ -52,11 +53,7 @@ public final class CassandraSmtpTestRuleFactory {
                     .toInstance(BaseHierarchicalConfiguration::new))
             .overrideWith(
                 binder -> binder.bind(ClusterConfiguration.class).toInstance(
-                    ClusterConfiguration.builder()
-                        .host(cassandraHost)
-                        .keyspace("testing")
-                        .createKeyspace()
-                        .replicationFactor(1)
+                    DockerCassandra.configurationBuilder(cassandraHost)
                         .build()),
                 binder -> binder.bind(DNSService.class).toInstance(dnsService));
     }
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
index 9277651..423658a 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
@@ -23,6 +23,7 @@ import static org.apache.james.CassandraJamesServerMain.ALL_BUT_JMX_CASSANDRA_MO
 import static org.apache.james.JamesServerContract.DOMAIN_LIST_CONFIGURATION_MODULE;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
+import org.apache.james.backends.cassandra.DockerCassandra;
 import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 import org.apache.james.mailbox.extractor.TextExtractor;
 import org.apache.james.mailbox.store.search.PDFTextExtractor;
@@ -34,24 +35,33 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 import com.google.inject.CreationException;
 
 class AuthenticatedCassandraJamesServerTest {
+    private static final String CASSANDRA_USER = DockerCassandra.CASSANDRA_TESTING_USER;
+    private static final String VALID_PASSWORD = DockerCassandra.CASSANDRA_TESTING_PASSWORD;
+    private static final String INVALID_PASSWORD = "bad";
+
+    private final CassandraExtension cassandraExtension = new CassandraExtension();
+
     @Nested
     class AuthenticationTest implements JamesServerContract {
         @RegisterExtension
         JamesServerExtension testExtension = new JamesServerBuilder()
             .extension(new DockerElasticSearchExtension())
-            .extension(CassandraAuthenticationExtension.withValidCredentials())
+            .extension(cassandraExtension)
             .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
                 .combineWith(ALL_BUT_JMX_CASSANDRA_MODULE)
                 .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
                 .overrideWith(TestJMAPServerModule.limitToTenMessages())
                 .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
+            .overrideServerModule(binder -> binder.bind(ClusterConfiguration.class)
+                .toInstance(DockerCassandra.configurationBuilder(cassandraExtension.getCassandra().getHost())
+                    .username(CASSANDRA_USER)
+                    .password(VALID_PASSWORD)
+                    .build()))
             .build();
     }
 
     @Nested
     class SslTest {
-        private final CassandraExtension cassandraExtension = new CassandraExtension();
-
         @RegisterExtension
         JamesServerExtension testExtension = new JamesServerBuilder()
             .extension(new DockerElasticSearchExtension())
@@ -63,13 +73,9 @@ class AuthenticatedCassandraJamesServerTest {
                 .overrideWith(TestJMAPServerModule.limitToTenMessages())
                 .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
             .overrideServerModule(binder -> binder.bind(ClusterConfiguration.class)
-                .toInstance(ClusterConfiguration.builder()
-                    .host(cassandraExtension.getCassandra().getHost())
-                    .keyspace("testing")
-                    .createKeyspace()
-                    .replicationFactor(1)
-                    .maxRetry(1)
-                    .minDelay(100)
+                .toInstance(DockerCassandra.configurationBuilder(cassandraExtension.getCassandra().getHost())
+                    .username(CASSANDRA_USER)
+                    .password(VALID_PASSWORD)
                     .useSsl()
                     .build()))
             .build();
@@ -87,13 +93,19 @@ class AuthenticatedCassandraJamesServerTest {
         @RegisterExtension
         JamesServerExtension testExtension = new JamesServerBuilder()
             .extension(new DockerElasticSearchExtension())
-            .extension(CassandraAuthenticationExtension.withInvalidCredentials())
+            .extension(cassandraExtension)
             .disableAutoStart()
             .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
                 .combineWith(ALL_BUT_JMX_CASSANDRA_MODULE)
                 .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
                 .overrideWith(TestJMAPServerModule.limitToTenMessages())
                 .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
+            .overrideServerModule(binder -> binder.bind(ClusterConfiguration.class)
+                .toInstance(DockerCassandra.configurationBuilder(cassandraExtension.getCassandra().getHost())
+                    .username(CASSANDRA_USER)
+                    .password(INVALID_PASSWORD)
+                    .maxRetry(1)
+                    .build()))
             .build();
 
         @Test
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraAuthenticationExtension.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraAuthenticationExtension.java
deleted file mode 100644
index 35daa6a..0000000
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraAuthenticationExtension.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************
- * 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;
-
-import org.apache.james.backends.cassandra.DockerCassandra;
-import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
-import org.apache.james.server.CassandraTruncateTableTask;
-
-import com.google.inject.Module;
-import com.google.inject.multibindings.Multibinder;
-import com.google.inject.util.Modules;
-
-public class CassandraAuthenticationExtension implements GuiceModuleTestExtension {
-    private static final String VALID_PASSWORD = "cassandra";
-    private static final String INVALID_PASSWORD = "bad";
-    private static final DockerCassandra authenticatedCassandra = new DockerCassandra("cassandra_3_11_3_auth",
-        dockerfileBuilder -> dockerfileBuilder
-            .run("echo 'authenticator: PasswordAuthenticator' >> /etc/cassandra/cassandra.yaml"));
-
-    static {
-        authenticatedCassandra.start();
-    }
-
-    public static CassandraAuthenticationExtension withValidCredentials() {
-        return new CassandraAuthenticationExtension(ClusterConfiguration.builder()
-            .password(VALID_PASSWORD)
-            .maxRetry(20)
-            .minDelay(5000));
-    }
-
-    public static CassandraAuthenticationExtension withInvalidCredentials() {
-        return new CassandraAuthenticationExtension(ClusterConfiguration.builder()
-            .password(INVALID_PASSWORD)
-            .maxRetry(1)
-            .minDelay(100));
-    }
-
-    private final ClusterConfiguration.Builder configurationBuilder;
-
-    private CassandraAuthenticationExtension(ClusterConfiguration.Builder configurationBuilder) {
-        this.configurationBuilder = configurationBuilder;
-    }
-
-    @Override
-    public Module getModule() {
-        return Modules.combine((binder) -> binder.bind(ClusterConfiguration.class)
-                .toInstance(configurationBuilder
-                    .host(authenticatedCassandra.getHost())
-                    .keyspace("testing")
-                    .createKeyspace()
-                    .username("cassandra")
-                    .replicationFactor(1)
-                    .build()),
-            binder -> Multibinder.newSetBinder(binder, CleanupTasksPerformer.CleanupTask.class)
-                .addBinding()
-                .to(CassandraTruncateTableTask.class));
-    }
-}
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
index b80c9e1..99d0d33 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
@@ -27,6 +27,7 @@ import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
 import java.nio.charset.Charset;
 
+import org.apache.james.backends.cassandra.DockerCassandra;
 import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.protocols.ImapGuiceProbe;
@@ -88,9 +89,10 @@ class CassandraNodeConfTest {
         @RegisterExtension
         JamesServerExtension testExtension = extensionBuilder()
             .overrideServerModule(binder -> binder.bind(ClusterConfiguration.class)
-                .toInstance(clusterWithHosts(
-                    Host.from(unreachableNode, 9042),
-                    cassandra.getHost())))
+                .toInstance(DockerCassandra.configurationBuilder(
+                        Host.from(unreachableNode, 9042),
+                        cassandra.getHost())
+                    .build()))
             .build();
 
         @Test
@@ -106,8 +108,9 @@ class CassandraNodeConfTest {
         @RegisterExtension
         JamesServerExtension testExtension =  extensionBuilder()
             .overrideServerModule(binder -> binder.bind(ClusterConfiguration.class)
-                .toInstance(clusterWithHosts(
-                    Host.from(getDockerHostIp(), cassandra.getMappedPort(CASSANDRA_PORT)))))
+                .toInstance(DockerCassandra.configurationBuilder(
+                        Host.from(getDockerHostIp(), cassandra.getMappedPort(CASSANDRA_PORT)))
+                    .build()))
             .build();
 
         @Test
@@ -122,17 +125,6 @@ class CassandraNodeConfTest {
         assertThat(getServerConnectionResponse(socketChannel)).startsWith("* OK JAMES IMAP4rev1 Server");
     }
 
-    private ClusterConfiguration clusterWithHosts(Host... hosts) {
-        return ClusterConfiguration.builder()
-            .hosts(hosts)
-            .keyspace("apache_james")
-            .createKeyspace()
-            .replicationFactor(1)
-            .maxRetry(10)
-            .minDelay(5000)
-            .build();
-    }
-
     private String getServerConnectionResponse(SocketChannel socketChannel) throws IOException {
         ByteBuffer byteBuffer = ByteBuffer.allocate(1000);
         socketChannel.read(byteBuffer);
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DockerCassandraRule.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DockerCassandraRule.java
index 542eef3..d003410 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DockerCassandraRule.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/DockerCassandraRule.java
@@ -19,6 +19,7 @@
 
 package org.apache.james;
 
+import org.apache.james.backends.cassandra.DockerCassandra;
 import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 import org.apache.james.server.CassandraTruncateTableTask;
 import org.apache.james.util.Host;
@@ -46,11 +47,7 @@ public class DockerCassandraRule implements GuiceModuleTestRule {
     @Override
     public Module getModule() {
         return Modules.combine((binder) -> binder.bind(ClusterConfiguration.class)
-            .toInstance(ClusterConfiguration.builder()
-                .host(cassandraContainer.getHost())
-                .keyspace("testing")
-                .createKeyspace()
-                .replicationFactor(1)
+            .toInstance(DockerCassandra.configurationBuilder(cassandraContainer.getHost())
                 .maxRetry(20)
                 .minDelay(5000)
                 .build()),


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


[james-project] 09/29: JAMES-3061 Simplify CassandraCluster resources cleanup

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 f743a4b1a64162920ea1e16091ecced1fe719d2b
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Mon Feb 24 18:21:29 2020 +0700

    JAMES-3061 Simplify CassandraCluster resources cleanup
---
 ...ventSourcingDLPConfigurationStoreExtension.java | 22 ++++++++--------------
 .../cassandra/CassandraDomainListTest.java         |  3 +--
 .../CassandraRecipientRewriteTableV6Test.java      |  3 +--
 .../CassandraRecipientRewriteTableV7Test.java      |  3 +--
 .../cassandra/CassandraSieveRepositoryTest.java    |  3 +--
 .../access/CassandraAccessTokenRepositoryTest.java |  3 +--
 .../CassandraNotificationRegistryTest.java         |  3 +--
 .../vacation/CassandraVacationRepositoryTest.java  |  3 +--
 8 files changed, 15 insertions(+), 28 deletions(-)

diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/dlp/eventsourcing/cassandra/CassandraEventSourcingDLPConfigurationStoreExtension.java b/server/data/data-cassandra/src/test/java/org/apache/james/dlp/eventsourcing/cassandra/CassandraEventSourcingDLPConfigurationStoreExtension.java
index 1dedaf4..c128d12 100644
--- a/server/data/data-cassandra/src/test/java/org/apache/james/dlp/eventsourcing/cassandra/CassandraEventSourcingDLPConfigurationStoreExtension.java
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/dlp/eventsourcing/cassandra/CassandraEventSourcingDLPConfigurationStoreExtension.java
@@ -19,8 +19,7 @@
 
 package org.apache.james.dlp.eventsourcing.cassandra;
 
-import org.apache.james.backends.cassandra.CassandraCluster;
-import org.apache.james.backends.cassandra.DockerCassandraExtension;
+import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.dlp.api.DLPConfigurationStore;
 import org.apache.james.dlp.eventsourcing.EventSourcingDLPConfigurationStore;
 import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStore;
@@ -37,35 +36,30 @@ import org.junit.jupiter.api.extension.ParameterResolver;
 
 public class CassandraEventSourcingDLPConfigurationStoreExtension implements BeforeAllCallback, AfterAllCallback, AfterEachCallback, ParameterResolver {
 
-    private final DockerCassandraExtension dockerCassandraExtension;
-    private CassandraCluster cassandra;
+    private final CassandraClusterExtension cassandraExtension;
 
     public CassandraEventSourcingDLPConfigurationStoreExtension() {
-        dockerCassandraExtension = new DockerCassandraExtension();
+        cassandraExtension = new CassandraClusterExtension(CassandraEventStoreModule.MODULE());
     }
 
     @Override
     public void beforeAll(ExtensionContext context) throws Exception {
-        dockerCassandraExtension.beforeAll(context);
-        cassandra = CassandraCluster.create(
-            CassandraEventStoreModule.MODULE(),
-            dockerCassandraExtension.getDockerCassandra().getHost());
+        cassandraExtension.beforeAll(context);
     }
 
     @Override
     public void afterEach(ExtensionContext context) {
-        cassandra.clearTables();
+        cassandraExtension.afterEach(context);
     }
 
     @Override
     public void afterAll(ExtensionContext context) throws Exception {
-        cassandra.closeCluster();
-        dockerCassandraExtension.afterAll(context);
+        cassandraExtension.afterAll(context);
     }
 
     @Override
     public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
-        return (parameterContext.getParameter().getType() == DLPConfigurationStore.class);
+        return parameterContext.getParameter().getType() == DLPConfigurationStore.class;
     }
 
     @Override
@@ -75,7 +69,7 @@ public class CassandraEventSourcingDLPConfigurationStoreExtension implements Bef
             .withoutNestedType();
 
         EventStoreDao eventStoreDao = new EventStoreDao(
-            cassandra.getConf(),
+            cassandraExtension.getCassandraCluster().getConf(),
             jsonEventSerializer);
 
         return new EventSourcingDLPConfigurationStore(new CassandraEventStore(eventStoreDao));
diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/domainlist/cassandra/CassandraDomainListTest.java b/server/data/data-cassandra/src/test/java/org/apache/james/domainlist/cassandra/CassandraDomainListTest.java
index 88c63e5..9e869fb 100644
--- a/server/data/data-cassandra/src/test/java/org/apache/james/domainlist/cassandra/CassandraDomainListTest.java
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/domainlist/cassandra/CassandraDomainListTest.java
@@ -43,8 +43,7 @@ public class CassandraDomainListTest extends AbstractDomainListTest {
 
     @After
     public void tearDown() {
-        cassandra.clearTables();
-        cassandra.closeCluster();
+        cassandra.close();
     }
 
     @Override
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 41386ef..9412389 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
@@ -56,8 +56,7 @@ public class CassandraRecipientRewriteTableV6Test extends AbstractRecipientRewri
     @After
     public void tearDown() throws Exception {
         super.tearDown();
-        cassandra.clearTables();
-        cassandra.closeCluster();
+        cassandra.close();
     }
 
     @Override
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 381809f..0523ed6 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
@@ -56,8 +56,7 @@ public class CassandraRecipientRewriteTableV7Test extends AbstractRecipientRewri
     @After
     public void tearDown() throws Exception {
         super.tearDown();
-        cassandra.clearTables();
-        cassandra.closeCluster();
+        cassandra.close();
     }
 
     @Override
diff --git a/server/data/data-cassandra/src/test/java/org/apache/james/sieve/cassandra/CassandraSieveRepositoryTest.java b/server/data/data-cassandra/src/test/java/org/apache/james/sieve/cassandra/CassandraSieveRepositoryTest.java
index c44616f..c28d7ba 100644
--- a/server/data/data-cassandra/src/test/java/org/apache/james/sieve/cassandra/CassandraSieveRepositoryTest.java
+++ b/server/data/data-cassandra/src/test/java/org/apache/james/sieve/cassandra/CassandraSieveRepositoryTest.java
@@ -43,8 +43,7 @@ public class CassandraSieveRepositoryTest extends AbstractSieveRepositoryTest {
     
     @After
     public void tearDown() {
-        cassandra.clearTables();
-        cassandra.closeCluster();
+        cassandra.close();
     }
 
     @Override
diff --git a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenRepositoryTest.java b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenRepositoryTest.java
index 8051eae..5e2c7b3 100644
--- a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenRepositoryTest.java
+++ b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/access/CassandraAccessTokenRepositoryTest.java
@@ -43,8 +43,7 @@ public class CassandraAccessTokenRepositoryTest extends AccessTokenRepositoryTes
     
     @After
     public void tearDown() {
-        cassandra.clearTables();
-        cassandra.closeCluster();
+        cassandra.close();
     }
 
     @Override
diff --git a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistryTest.java b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistryTest.java
index fc38096..d22d048 100644
--- a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistryTest.java
+++ b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistryTest.java
@@ -44,8 +44,7 @@ public class CassandraNotificationRegistryTest extends AbstractNotificationRegis
 
     @After
     public void tearDown() {
-        cassandra.clearTables();
-        cassandra.closeCluster();
+        cassandra.close();
     }
 
     @Override
diff --git a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepositoryTest.java b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepositoryTest.java
index 19d4cf9..c45e956 100644
--- a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepositoryTest.java
+++ b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepositoryTest.java
@@ -51,8 +51,7 @@ public class CassandraVacationRepositoryTest extends AbstractVacationRepositoryT
 
     @After
     public void tearDown() {
-        cassandra.clearTables();
-        cassandra.closeCluster();
+        cassandra.close();
     }
 
     @Override


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


[james-project] 22/29: [REACTOR] CassandraUserMailboxRightsDAO should merge flux on updates

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 4a681409bfa7ca403d10c4deb1db7b5b5d63fac6
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Feb 27 14:39:15 2020 +0700

    [REACTOR] CassandraUserMailboxRightsDAO should merge flux on updates
    
    Before needless synchronisation was performed, waiting for all insert to
    complete, all delete to complete, and all insert
    
    Now merge can eagerly subscribe each streams insides.
---
 .../cassandra/mail/CassandraUserMailboxRightsDAO.java    | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUserMailboxRightsDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUserMailboxRightsDAO.java
index 127b5be..7586c96 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUserMailboxRightsDAO.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraUserMailboxRightsDAO.java
@@ -101,29 +101,27 @@ public class CassandraUserMailboxRightsDAO {
     public Mono<Void> update(CassandraId cassandraId, ACLDiff aclDiff) {
         PositiveUserACLDiff userACLDiff = new PositiveUserACLDiff(aclDiff);
         return Flux.merge(
-            addAll(cassandraId, userACLDiff.addedEntries()),
-            removeAll(cassandraId, userACLDiff.removedEntries()),
-            addAll(cassandraId, userACLDiff.changedEntries()))
+                addAll(cassandraId, userACLDiff.addedEntries()),
+                removeAll(cassandraId, userACLDiff.removedEntries()),
+                addAll(cassandraId, userACLDiff.changedEntries()))
             .then();
     }
 
-    private Mono<Void> removeAll(CassandraId cassandraId, Stream<MailboxACL.Entry> removedEntries) {
+    private Flux<Void> removeAll(CassandraId cassandraId, Stream<MailboxACL.Entry> removedEntries) {
         return Flux.fromStream(removedEntries)
             .flatMap(entry -> cassandraAsyncExecutor.executeVoid(
                 delete.bind()
                     .setString(USER_NAME, entry.getKey().getName())
-                    .setUUID(MAILBOX_ID, cassandraId.asUuid())))
-            .then();
+                    .setUUID(MAILBOX_ID, cassandraId.asUuid())));
     }
 
-    private Mono<Void> addAll(CassandraId cassandraId, Stream<MailboxACL.Entry> addedEntries) {
+    private Flux<Void> addAll(CassandraId cassandraId, Stream<MailboxACL.Entry> addedEntries) {
         return Flux.fromStream(addedEntries)
             .flatMap(entry -> cassandraAsyncExecutor.executeVoid(
                 insert.bind()
                     .setString(USER_NAME, entry.getKey().getName())
                     .setUUID(MAILBOX_ID, cassandraId.asUuid())
-                    .setString(RIGHTS, entry.getValue().serialize())))
-            .then();
+                    .setString(RIGHTS, entry.getValue().serialize())));
     }
 
     public Mono<Optional<Rfc4314Rights>> retrieve(Username userName, CassandraId mailboxId) {


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


[james-project] 19/29: JAMES-3074 s/UidValidity::random/UidValidity::generate/

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 7efbf9235274eac79ff06937e08d949c8d94439e
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Feb 28 09:31:10 2020 +0700

    JAMES-3074 s/UidValidity::random/UidValidity::generate/
---
 .../api/src/main/java/org/apache/james/mailbox/model/UidValidity.java | 2 +-
 .../src/test/java/org/apache/james/mailbox/model/UidValidityTest.java | 4 ++--
 .../events/ElasticSearchListeningMessageSearchIndexTest.java          | 2 +-
 .../src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java | 2 +-
 .../main/java/org/apache/james/mailbox/store/StoreMailboxManager.java | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
index c93cb2a..05e0f03 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
@@ -38,7 +38,7 @@ public class UidValidity {
      *
      * See https://issues.apache.org/jira/browse/JAMES-3074 for details
      */
-    public static  UidValidity random() {
+    public static  UidValidity generate() {
         return fromSupplier(RANDOM::nextLong);
     }
 
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java
index f48c527..89e25a4 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java
@@ -103,7 +103,7 @@ class UidValidityTest {
     // Sampling test
     @RepeatedTest(10000)
     void randomShouldGenerateValidValues() {
-        assertThatCode(UidValidity::random)
+        assertThatCode(UidValidity::generate)
             .doesNotThrowAnyException();
     }
 
@@ -112,7 +112,7 @@ class UidValidityTest {
     void randomShouldNotLeadToCollision() {
         int count = 1000000;
         long distinctCount = IntStream.range(0, count)
-            .mapToObj(any -> UidValidity.random())
+            .mapToObj(any -> UidValidity.generate())
             .distinct()
             .count();
 
diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
index 49424b4..f6d1391 100644
--- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
+++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
@@ -178,7 +178,7 @@ class ElasticSearchListeningMessageSearchIndexTest {
             messageToElasticSearchJson, sessionProvider, new MailboxIdRoutingKeyFactory());
         session = sessionProvider.createSystemSession(USERNAME);
 
-        mailbox = mapperFactory.getMailboxMapper(session).create(MailboxPath.forUser(USERNAME, DefaultMailboxes.INBOX), UidValidity.random());
+        mailbox = mapperFactory.getMailboxMapper(session).create(MailboxPath.forUser(USERNAME, DefaultMailboxes.INBOX), UidValidity.generate());
     }
 
     @Test
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
index ac8432f..6809c8f 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
@@ -341,7 +341,7 @@ public class MaildirFolder {
      * @return the new uidValidity
      */
     private UidValidity resetUidValidity() throws IOException {
-        UidValidity uidValidity = UidValidity.random();
+        UidValidity uidValidity = UidValidity.generate();
         setUidValidity(uidValidity);
         return uidValidity;
     }
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 e7cd367..e9ad7a4 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
@@ -373,7 +373,7 @@ public class StoreMailboxManager implements MailboxManager {
                 MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(mailboxSession);
                 try {
                     mapper.execute(Mapper.toTransaction(() -> {
-                        Mailbox mailbox = mapper.create(mailboxPath, UidValidity.random());
+                        Mailbox mailbox = mapper.create(mailboxPath, UidValidity.generate());
                         mailboxIds.add(mailbox.getMailboxId());
                         // notify listeners
                         eventBus.dispatch(EventFactory.mailboxAdded()


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


[james-project] 17/29: JAMES-3074 Tests should be using UidValidity::ofValid

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 d6a921cea2ddfe9fcf4737b8dcf62dbae63b1406
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Feb 26 11:45:17 2020 +0700

    JAMES-3074 Tests should be using UidValidity::ofValid
---
 .../org/apache/james/mailbox/model/MailboxAssertingToolTest.java  | 7 ++++---
 .../org/apache/james/mailbox/backup/MailboxMessageFixture.java    | 8 ++++----
 .../mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java    | 2 +-
 .../mailbox/cassandra/mail/CassandraMailboxCounterDAOTest.java    | 2 +-
 .../james/mailbox/cassandra/mail/CassandraMailboxDAOTest.java     | 4 ++--
 .../cassandra/mail/CassandraMailboxMapperConcurrencyTest.java     | 2 +-
 .../james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java  | 2 +-
 .../james/mailbox/cassandra/mail/CassandraModSeqProviderTest.java | 2 +-
 .../james/mailbox/cassandra/mail/CassandraUidProviderTest.java    | 2 +-
 .../cassandra/mail/migration/MailboxPathV2MigrationTest.java      | 2 +-
 .../events/ElasticSearchListeningMessageSearchIndexTest.java      | 2 +-
 .../lucene/search/LuceneMailboxMessageSearchIndexTest.java        | 6 +++---
 .../mailbox/inmemory/InMemoryCombinationManagerTestSystem.java    | 4 +---
 .../james/mailbox/inmemory/InMemoryMessageManagerTestSystem.java  | 4 +---
 .../james/mailbox/spamassassin/SpamAssassinListenerTest.java      | 2 +-
 .../org/apache/james/mailbox/store/StoreRightManagerTest.java     | 2 +-
 .../james/mailbox/store/mail/model/ListMailboxAssertTest.java     | 2 +-
 .../james/mailbox/store/mail/model/ListMessageAssertTest.java     | 2 +-
 .../james/mailbox/store/mail/model/MailboxMapperACLTest.java      | 2 +-
 .../apache/james/mailbox/store/mail/model/MailboxMapperTest.java  | 2 +-
 .../james/mailbox/store/mail/model/MessageIdMapperTest.java       | 2 +-
 .../apache/james/mailbox/store/mail/model/MessageMapperTest.java  | 2 +-
 .../apache/james/mailbox/store/mail/model/MessageMoveTest.java    | 2 +-
 .../mailbox/store/mail/model/MessageWithAttachmentMapperTest.java | 2 +-
 .../mailbox/store/quota/DefaultUserQuotaRootResolverTest.java     | 4 ++--
 .../org/apache/james/mailbox/store/quota/QuotaCheckerTest.java    | 2 +-
 .../james/imap/encode/MailboxStatusResponseEncoderTest.java       | 2 +-
 .../java/org/apache/james/imap/processor/CopyProcessorTest.java   | 5 +++--
 .../java/org/apache/james/imap/processor/MoveProcessorTest.java   | 5 +++--
 .../james/imap/processor/base/MailboxEventAnalyserTest.java       | 2 +-
 .../org/apache/james/adapter/mailbox/MailboxManagementTest.java   | 2 +-
 31 files changed, 45 insertions(+), 46 deletions(-)

diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingToolTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingToolTest.java
index 8e3377f..a88498e 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingToolTest.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingToolTest.java
@@ -31,7 +31,8 @@ class MailboxAssertingToolTest {
     private static final Username USER = Username.of("user");
     private static final Username USER1 = Username.of("user1");
 
-    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(42);
+    private static final UidValidity UID_VALIDITY_2 = UidValidity.ofValid(43);
     private static final TestId MAILBOX_ID = TestId.of(24);
 
     @Nested
@@ -83,7 +84,7 @@ class MailboxAssertingToolTest {
         @Test
         void isEqualToShouldFailWithNotEqualUidValidity() {
             Mailbox mailbox1 = new Mailbox(MailboxPath.forUser(USER, "name"), UID_VALIDITY, MAILBOX_ID);
-            Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(USER, "name"), UidValidity.of(UID_VALIDITY.asLong() + 1), MAILBOX_ID);
+            Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(USER, "name"), UID_VALIDITY_2, MAILBOX_ID);
 
             assertThatThrownBy(() -> MailboxAssertingTool.assertThat(mailbox1).isEqualTo(mailbox2))
                 .isInstanceOf(AssertionError.class);
@@ -157,7 +158,7 @@ class MailboxAssertingToolTest {
         @Test
         void isEqualToShouldFailWithNotEqualUidValidity() {
             Mailbox mailbox1 = new Mailbox(MailboxPath.forUser(USER, "name"), UID_VALIDITY, MAILBOX_ID);
-            Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(USER, "name"), UidValidity.of(UID_VALIDITY.asLong() + 1), MAILBOX_ID);
+            Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(USER, "name"), UID_VALIDITY_2, MAILBOX_ID);
 
             assertThatThrownBy(() -> {
                     SoftAssertions.assertSoftly(softly -> {
diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
index 50f8a76..f833839 100644
--- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
+++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
@@ -101,10 +101,10 @@ public interface MailboxMessageFixture {
     MailboxPath MAILBOX_PATH_USER1_MAILBOX2 = MailboxPath.forUser(USER, MAILBOX_2_NAME);
     MailboxPath MAILBOX_PATH_OTHER_USER_MAILBOX1 = MailboxPath.forUser(OTHER_USER, MAILBOX_OTHER_USER_NAME);
 
-    Mailbox MAILBOX_1 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX1, UidValidity.of(42), MAILBOX_ID_1);
-    Mailbox MAILBOX_1_OTHER_USER = new Mailbox(MAILBOX_PATH_OTHER_USER_MAILBOX1, UidValidity.of(42), MAILBOX_ID_11);
-    Mailbox MAILBOX_1_SUB_1 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX1_SUB_1, UidValidity.of(420), TestId.of(11L));
-    Mailbox MAILBOX_2 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX2, UidValidity.of(43), MAILBOX_ID_2);
+    Mailbox MAILBOX_1 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX1, UidValidity.ofValid(42), MAILBOX_ID_1);
+    Mailbox MAILBOX_1_OTHER_USER = new Mailbox(MAILBOX_PATH_OTHER_USER_MAILBOX1, UidValidity.ofValid(42), MAILBOX_ID_11);
+    Mailbox MAILBOX_1_SUB_1 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX1_SUB_1, UidValidity.ofValid(420), TestId.of(11L));
+    Mailbox MAILBOX_2 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX2, UidValidity.ofValid(43), MAILBOX_ID_2);
 
     List<MailboxAnnotation> NO_ANNOTATION = ImmutableList.of();
 
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
index d100737..ad0f2be 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
@@ -56,7 +56,7 @@ class CassandraIndexTableHandlerTest {
     private static final CassandraId MAILBOX_ID = CassandraId.timeBased();
     private static final MessageUid MESSAGE_UID = MessageUid.of(18L);
     private static final CassandraMessageId CASSANDRA_MESSAGE_ID = new CassandraMessageId.Factory().generate();
-    private static final UidValidity UID_VALIDITY = UidValidity.of(15);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(15);
     private static final ModSeq MODSEQ = ModSeq.of(17);
 
     @RegisterExtension
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 b87fdd3..15f5939 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
@@ -35,7 +35,7 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraMailboxCounterDAOTest {
-    private static final UidValidity UID_VALIDITY = UidValidity.of(15);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(15);
     private static final CassandraId MAILBOX_ID = CassandraId.timeBased();
 
     @RegisterExtension
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAOTest.java
index f13a96f..9aa1486 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAOTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAOTest.java
@@ -41,8 +41,8 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraMailboxDAOTest {
-    private static final UidValidity UID_VALIDITY_1 = UidValidity.of(145);
-    private static final UidValidity UID_VALIDITY_2 = UidValidity.of(147);
+    private static final UidValidity UID_VALIDITY_1 = UidValidity.ofValid(145);
+    private static final UidValidity UID_VALIDITY_2 = UidValidity.ofValid(147);
     private static final Username USER = Username.of("user");
     private static final MailboxPath NEW_MAILBOX_PATH = MailboxPath.forUser(USER, "xyz");
     private static CassandraId CASSANDRA_ID_1 = CassandraId.timeBased();
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java
index 54e7290..c239e4c 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java
@@ -42,7 +42,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraMailboxMapperConcurrencyTest {
 
-    private static final UidValidity UID_VALIDITY = UidValidity.of(52);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(52);
     private static final MailboxPath MAILBOX_PATH = MailboxPath.forUser(Username.of("user"), "name");
     private static final int THREAD_COUNT = 10;
     private static final int OPERATION_COUNT = 10;
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 c724053..986fe8b 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
@@ -59,7 +59,7 @@ import com.github.fge.lambdas.Throwing;
 import com.github.fge.lambdas.runnable.ThrowingRunnable;
 
 class CassandraMailboxMapperTest {
-    private static final UidValidity UID_VALIDITY = UidValidity.of(52);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(52);
     private static final Username USER = Username.of("user");
     private static final CassandraId MAILBOX_ID = CassandraId.timeBased();
     private static final MailboxPath MAILBOX_PATH = MailboxPath.forUser(USER, "name");
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProviderTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProviderTest.java
index 6c328a4..9d25206 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProviderTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProviderTest.java
@@ -56,7 +56,7 @@ class CassandraModSeqProviderTest {
     void setUp(CassandraCluster cassandra) {
         modSeqProvider = new CassandraModSeqProvider(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION);
         MailboxPath path = new MailboxPath("gsoc", Username.of("ieugen"), "Trash");
-        mailbox = new Mailbox(path, UidValidity.of(1234), CASSANDRA_ID);
+        mailbox = new Mailbox(path, UidValidity.ofValid(1234), CASSANDRA_ID);
     }
 
     @Test
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProviderTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProviderTest.java
index 80c43b0..53bcdc1 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProviderTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProviderTest.java
@@ -56,7 +56,7 @@ class CassandraUidProviderTest {
     void setUp(CassandraCluster cassandra) {
         uidProvider = new CassandraUidProvider(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION);
         MailboxPath path = new MailboxPath("gsoc", Username.of("ieugen"), "Trash");
-        mailbox = new Mailbox(path, UidValidity.of(1234), CASSANDRA_ID);
+        mailbox = new Mailbox(path, UidValidity.ofValid(1234), CASSANDRA_ID);
     }
 
     @Test
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 82ee289..7412e05 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
@@ -50,7 +50,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 class MailboxPathV2MigrationTest {
 
     private static final MailboxPath MAILBOX_PATH_1 = MailboxPath.forUser(Username.of("bob"), "Important");
-    private static final UidValidity UID_VALIDITY_1 = UidValidity.of(452);
+    private static final UidValidity UID_VALIDITY_1 = UidValidity.ofValid(452);
     private static final CassandraId MAILBOX_ID_1 = CassandraId.timeBased();
 
     public static final CassandraModule MODULES = CassandraModule.aggregateModules(
diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
index 5a94b95..49424b4 100644
--- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
+++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
@@ -178,7 +178,7 @@ class ElasticSearchListeningMessageSearchIndexTest {
             messageToElasticSearchJson, sessionProvider, new MailboxIdRoutingKeyFactory());
         session = sessionProvider.createSystemSession(USERNAME);
 
-        mailbox = mapperFactory.getMailboxMapper(session).create(MailboxPath.forUser(USERNAME, DefaultMailboxes.INBOX), UidValidity.of(MAILBOX_ID.id));
+        mailbox = mapperFactory.getMailboxMapper(session).create(MailboxPath.forUser(USERNAME, DefaultMailboxes.INBOX), UidValidity.random());
     }
 
     @Test
diff --git a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java
index 6ff52fb..1b45f08 100644
--- a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java
+++ b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java
@@ -62,9 +62,9 @@ class LuceneMailboxMessageSearchIndexTest {
     static final TestId TEST_ID_3 = TestId.of(2);
 
     static final Username BOB = Username.of("bob");
-    Mailbox mailbox = new Mailbox(MailboxPath.forUser(BOB, "box"), UidValidity.of(18), TEST_ID_1);
-    Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(BOB, "box"), UidValidity.of(19), TEST_ID_2);
-    Mailbox mailbox3 = new Mailbox(MailboxPath.forUser(BOB, "box"), UidValidity.of(12), TEST_ID_3);
+    Mailbox mailbox = new Mailbox(MailboxPath.forUser(BOB, "box"), UidValidity.ofValid(18), TEST_ID_1);
+    Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(BOB, "box"), UidValidity.ofValid(19), TEST_ID_2);
+    Mailbox mailbox3 = new Mailbox(MailboxPath.forUser(BOB, "box"), UidValidity.ofValid(12), TEST_ID_3);
     LuceneMessageSearchIndex index;
     MailboxSession session;
 
diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryCombinationManagerTestSystem.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryCombinationManagerTestSystem.java
index 3087bef..be0c9d5 100644
--- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryCombinationManagerTestSystem.java
+++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryCombinationManagerTestSystem.java
@@ -29,8 +29,6 @@ import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.CombinationManagerTestSystem;
 
 public class InMemoryCombinationManagerTestSystem extends CombinationManagerTestSystem {
-    private static final UidValidity UID_VALIDITY = UidValidity.of(1024);
-
     private final InMemoryMailboxManager inMemoryMailboxManager;
 
     public InMemoryCombinationManagerTestSystem(MailboxManager mailboxManager, MessageIdManager messageIdManager) {
@@ -47,7 +45,7 @@ public class InMemoryCombinationManagerTestSystem extends CombinationManagerTest
     public Mailbox createMailbox(MailboxPath mailboxPath, MailboxSession session) throws MailboxException {
         inMemoryMailboxManager.createMailbox(mailboxPath, session);
         MessageManager messageManager = inMemoryMailboxManager.getMailbox(mailboxPath, session);
-        return new Mailbox(mailboxPath, UID_VALIDITY, messageManager.getId());
+        return messageManager.getMailboxEntity();
     }
 
 }
diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageManagerTestSystem.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageManagerTestSystem.java
index 4933ee5..89db34d 100644
--- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageManagerTestSystem.java
+++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageManagerTestSystem.java
@@ -29,8 +29,6 @@ import org.apache.james.mailbox.store.MessageManagerTestSystem;
 
 public class InMemoryMessageManagerTestSystem extends MessageManagerTestSystem {
 
-    private static final UidValidity UID_VALIDITY = UidValidity.of(1024);
-
     private final MailboxManager mailboxManager;
 
     public InMemoryMessageManagerTestSystem(MailboxManager mailboxManager) {
@@ -42,6 +40,6 @@ public class InMemoryMessageManagerTestSystem extends MessageManagerTestSystem {
     public Mailbox createMailbox(MailboxPath mailboxPath, MailboxSession mailboxSession) throws MailboxException {
         mailboxManager.createMailbox(mailboxPath, mailboxSession);
         MessageManager messageManager = mailboxManager.getMailbox(mailboxPath, mailboxSession);
-        return new Mailbox(mailboxPath, UID_VALIDITY, messageManager.getId());
+        return messageManager.getMailboxEntity();
     }
 }
diff --git a/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java b/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
index 4227d3b..f4bdc90 100644
--- a/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
+++ b/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
@@ -61,7 +61,7 @@ import org.junit.jupiter.api.Test;
 class SpamAssassinListenerTest {
     static final Username USER = Username.of("user");
     static final MailboxSession MAILBOX_SESSION = MailboxSessionUtil.create(USER);
-    static final UidValidity UID_VALIDITY = UidValidity.of(43);
+    static final UidValidity UID_VALIDITY = UidValidity.ofValid(43);
     static final TestMessageId MESSAGE_ID = TestMessageId.of(45);
 
     SpamAssassin spamAssassin;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreRightManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreRightManagerTest.java
index 7aa4a76..008c170 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreRightManagerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreRightManagerTest.java
@@ -59,7 +59,7 @@ import org.junit.jupiter.api.Test;
 class StoreRightManagerTest {
 
     static final MailboxId MAILBOX_ID = TestId.of(42);
-    static final UidValidity UID_VALIDITY = UidValidity.of(3421L);
+    static final UidValidity UID_VALIDITY = UidValidity.ofValid(3421L);
 
     StoreRightManager storeRightManager;
     MailboxSession aliceSession;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMailboxAssertTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMailboxAssertTest.java
index 0d158a6..97963f6 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMailboxAssertTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMailboxAssertTest.java
@@ -40,7 +40,7 @@ class ListMailboxAssertTest {
     static final String NAME = "name";
     static final Username USER = Username.of("user");
     static final String NAMESPACE = "namespace";
-    static final UidValidity UID_VALIDITY = UidValidity.of(42);
+    static final UidValidity UID_VALIDITY = UidValidity.ofValid(42);
     static final MailboxId MAILBOX_ID_1 = TestId.of(1);
     static final MailboxId MAILBOX_ID_2 = TestId.of(2);
     static final Mailbox MAILBOX_1 = new Mailbox(new MailboxPath(NAMESPACE, USER, NAME), UID_VALIDITY, MAILBOX_ID_1);
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java
index 99318de..63b2cbd 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java
@@ -50,7 +50,7 @@ class ListMessageAssertTest {
     static final String BODY_CONTENT2 = "Subject: Test2 \n\nBody2\n.\n";
     static final String BODY_CONTENT1 = "Subject: Test1 \n\nBody1\n.\n";
     static final int BODY_START = 16;
-    static final UidValidity UID_VALIDITY = UidValidity.of(42);
+    static final UidValidity UID_VALIDITY = UidValidity.ofValid(42);
     static final MailboxId MAILBOX_ID = TestId.of(1);
     static final MessageUid MESSAGE_UID = MessageUid.of(2);
     static final MessageId MESSAGE_ID = new DefaultMessageId();
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperACLTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperACLTest.java
index 744892f..7776c6a 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperACLTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperACLTest.java
@@ -38,7 +38,7 @@ import org.junit.jupiter.api.Test;
 import com.google.common.collect.ImmutableMap;
 
 public abstract class MailboxMapperACLTest {
-    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(42);
     private static final boolean POSITIVE = true;
     private static final boolean NEGATIVE = !POSITIVE;
     private static final Username USER = Username.of("user");
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java
index aee7ac5..7731554 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java
@@ -49,7 +49,7 @@ import org.junit.jupiter.api.Test;
 public abstract class MailboxMapperTest {
 
     private static final char DELIMITER = '.';
-    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(42);
     private static final Username BENWA = Username.of("benwa");
     private static final MailboxPath benwaInboxPath = MailboxPath.forUser(BENWA, "INBOX");
     private static final MailboxPath benwaWorkPath = MailboxPath.forUser(BENWA, "INBOX" + DELIMITER + "work");
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
index 731f35a..a14b98d 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
@@ -65,7 +65,7 @@ public abstract class MessageIdMapperTest {
 
     private static final char DELIMITER = '.';
     private static final int BODY_START = 16;
-    protected static final UidValidity UID_VALIDITY = UidValidity.of(42);
+    protected static final UidValidity UID_VALIDITY = UidValidity.ofValid(42);
 
     private MessageMapper messageMapper;
     private MailboxMapper mailboxMapper;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
index b199021..bd3b111 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
@@ -70,7 +70,7 @@ public abstract class MessageMapperTest {
     private static final char DELIMITER = '.';
     private static final int LIMIT = 10;
     private static final int BODY_START = 16;
-    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(42);
     private static final String USER_FLAG = "userFlag";
 
     private static final String CUSTOMS_USER_FLAGS_VALUE = "CustomsFlags";
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java
index 4542f2f..7ef5380 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java
@@ -48,7 +48,7 @@ public abstract class MessageMoveTest {
     private static final char DELIMITER = '.';
     private static final int LIMIT = 10;
     private static final int BODY_START = 16;
-    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(42);
 
     private MapperProvider mapperProvider;
     private MessageMapper messageMapper;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java
index f10a0b6..b096fd1 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java
@@ -55,7 +55,7 @@ public abstract class MessageWithAttachmentMapperTest {
 
     private static final int LIMIT = 10;
     private static final int BODY_START = 16;
-    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(42);
 
     private MapperProvider mapperProvider;
     private MessageMapper messageMapper;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java
index d744e15..82cf761 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java
@@ -49,9 +49,9 @@ class DefaultUserQuotaRootResolverTest {
     static final Username BENWA = Username.of("benwa");
     static final MailboxId MAILBOX_ID = TestId.of(42);
     static final MailboxPath MAILBOX_PATH = MailboxPath.inbox(BENWA);
-    static final Mailbox MAILBOX = new Mailbox(MAILBOX_PATH, UidValidity.of(10), MAILBOX_ID);
+    static final Mailbox MAILBOX = new Mailbox(MAILBOX_PATH, UidValidity.ofValid(10), MAILBOX_ID);
     static final MailboxPath MAILBOX_PATH_2 = MailboxPath.forUser(BENWA, "test");
-    static final Mailbox MAILBOX_2 = new Mailbox(MAILBOX_PATH_2, UidValidity.of(10), MAILBOX_ID);
+    static final Mailbox MAILBOX_2 = new Mailbox(MAILBOX_PATH_2, UidValidity.ofValid(10), MAILBOX_ID);
     static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("#private&benwa", Optional.empty());
     static final MailboxSession MAILBOX_SESSION = null;
 
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
index 9c09ab2..35a764d 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
@@ -49,7 +49,7 @@ class QuotaCheckerTest {
     static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("benwa", Optional.empty());
     static final MailboxId MAILBOX_ID = TestId.of(42);
     static final MailboxPath MAILBOX_PATH = MailboxPath.inbox(Username.of("benwa"));
-    static final Mailbox MAILBOX = new Mailbox(MAILBOX_PATH, UidValidity.of(10), MAILBOX_ID);
+    static final Mailbox MAILBOX = new Mailbox(MAILBOX_PATH, UidValidity.ofValid(10), MAILBOX_ID);
 
     QuotaRootResolver mockedQuotaRootResolver;
     QuotaManager mockedQuotaManager;
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/encode/MailboxStatusResponseEncoderTest.java b/protocols/imap/src/test/java/org/apache/james/imap/encode/MailboxStatusResponseEncoderTest.java
index 110feee..5ad5417 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/encode/MailboxStatusResponseEncoderTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/encode/MailboxStatusResponseEncoderTest.java
@@ -51,7 +51,7 @@ public class MailboxStatusResponseEncoderTest  {
         final Long messages = 2L;
         final Long recent = 3L;
         final MessageUid uidNext = MessageUid.of(5);
-        final UidValidity uidValidity = UidValidity.of(7L);
+        final UidValidity uidValidity = UidValidity.ofValid(7L);
         final Long unseen = 11L;
         final String mailbox = "A mailbox named desire";
 
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java
index 61a7580..11876d4 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java
@@ -60,6 +60,7 @@ import com.google.common.collect.Lists;
 public class CopyProcessorTest {
     private static final Username USERNAME = Username.of("username");
     private static final MailboxPath INBOX = MailboxPath.inbox(USERNAME);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(58L);
 
     private CopyProcessor testee;
     private ImapProcessor mockNextProcessor;
@@ -98,7 +99,7 @@ public class CopyProcessorTest {
         MessageManager targetMessageManager = mock(MessageManager.class);
         when(mockMailboxManager.getMailbox(INBOX, mailboxSession)).thenReturn(targetMessageManager);
         Mailbox mailbox = mock(Mailbox.class);
-        when(mailbox.getUidValidity()).thenReturn(UidValidity.of(58L));
+        when(mailbox.getUidValidity()).thenReturn(UID_VALIDITY);
         when(targetMessageManager.getMailboxEntity()).thenReturn(mailbox);
         StatusResponse okResponse = mock(StatusResponse.class);
         when(mockStatusResponseFactory.taggedOk(any(Tag.class), any(ImapCommand.class), any(HumanReadableText.class), any(StatusResponse.ResponseCode.class))).thenReturn(okResponse);
@@ -131,7 +132,7 @@ public class CopyProcessorTest {
         MessageManager targetMessageManager = mock(MessageManager.class);
         when(mockMailboxManager.getMailbox(INBOX, mailboxSession)).thenReturn(targetMessageManager);
         Mailbox mailbox = mock(Mailbox.class);
-        when(mailbox.getUidValidity()).thenReturn(UidValidity.of(58L));
+        when(mailbox.getUidValidity()).thenReturn(UID_VALIDITY);
         when(targetMessageManager.getMailboxEntity()).thenReturn(mailbox);
         StatusResponse okResponse = mock(StatusResponse.class);
         when(mockStatusResponseFactory.taggedOk(any(Tag.class), any(ImapCommand.class), any(HumanReadableText.class), any(StatusResponse.ResponseCode.class))).thenReturn(okResponse);
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java
index 3fafe5c..3c91299 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java
@@ -63,6 +63,7 @@ import com.google.common.collect.Lists;
 public class MoveProcessorTest {
     private static final Username USERNAME = Username.of("username");
     private static final MailboxPath INBOX = MailboxPath.inbox(USERNAME);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(58L);
 
     private MoveProcessor testee;
     private ImapProcessor mockNextProcessor;
@@ -114,7 +115,7 @@ public class MoveProcessorTest {
         MessageManager targetMessageManager = mock(MessageManager.class);
         when(mockMailboxManager.getMailbox(INBOX, mailboxSession)).thenReturn(targetMessageManager);
         Mailbox mailbox = mock(Mailbox.class);
-        when(mailbox.getUidValidity()).thenReturn(UidValidity.of(58L));
+        when(mailbox.getUidValidity()).thenReturn(UID_VALIDITY);
         when(targetMessageManager.getMailboxEntity()).thenReturn(mailbox);
         StatusResponse okResponse = mock(StatusResponse.class);
         when(mockStatusResponseFactory.taggedOk(any(Tag.class), any(ImapCommand.class), any(HumanReadableText.class), any(StatusResponse.ResponseCode.class))).thenReturn(okResponse);
@@ -147,7 +148,7 @@ public class MoveProcessorTest {
         MessageManager targetMessageManager = mock(MessageManager.class);
         when(mockMailboxManager.getMailbox(INBOX, mailboxSession)).thenReturn(targetMessageManager);
         Mailbox mailbox = mock(Mailbox.class);
-        when(mailbox.getUidValidity()).thenReturn(UidValidity.of(58L));
+        when(mailbox.getUidValidity()).thenReturn(UID_VALIDITY);
         when(targetMessageManager.getMailboxEntity()).thenReturn(mailbox);
         StatusResponse okResponse = mock(StatusResponse.class);
         when(mockStatusResponseFactory.taggedOk(any(Tag.class), any(ImapCommand.class), any(HumanReadableText.class), any(StatusResponse.ResponseCode.class))).thenReturn(okResponse);
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java
index 736a0f3..0fca17c 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java
@@ -117,7 +117,7 @@ public class MailboxEventAnalyserTest {
     private static final char PATH_DELIMITER = '.';
     private static final MailboxPath MAILBOX_PATH = new MailboxPath("namespace", USER, "name");
     private static final TestId MAILBOX_ID = TestId.of(36);
-    private static final UidValidity UID_VALIDITY = UidValidity.of(1024);
+    private static final UidValidity UID_VALIDITY = UidValidity.ofValid(1024);
     private static final Mailbox DEFAULT_MAILBOX = new Mailbox(MAILBOX_PATH, UID_VALIDITY, MAILBOX_ID);
     private static final MailboxListener.Added ADDED = EventFactory.added()
         .randomEventId()
diff --git a/server/container/mailbox-jmx/src/test/java/org/apache/james/adapter/mailbox/MailboxManagementTest.java b/server/container/mailbox-jmx/src/test/java/org/apache/james/adapter/mailbox/MailboxManagementTest.java
index 21c33c7..945e33e 100644
--- a/server/container/mailbox-jmx/src/test/java/org/apache/james/adapter/mailbox/MailboxManagementTest.java
+++ b/server/container/mailbox-jmx/src/test/java/org/apache/james/adapter/mailbox/MailboxManagementTest.java
@@ -48,7 +48,7 @@ import org.junit.jupiter.api.Test;
 public class MailboxManagementTest {
 
     public static final Username USER = Username.of("user");
-    public static final UidValidity UID_VALIDITY = UidValidity.of(10);
+    public static final UidValidity UID_VALIDITY = UidValidity.ofValid(10);
     public static final int LIMIT = 1;
 
     private MailboxManagerManagement mailboxManagerManagement;


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


[james-project] 05/29: JAMES-3061 Starting to provision cassandra testing users and keyspaces

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 60752b1b064de3042dc756c3b722448aa314caca
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Mon Feb 24 18:09:23 2020 +0700

    JAMES-3061 Starting to provision cassandra testing users and keyspaces
    
    99.9% cassandra tests in James need the keyspace and testing users to
    be provided. From my research, there is no better place to put this business
    than DockerCassandra. Provision right after the docker started up.
---
 .../james/backends/cassandra/DockerCassandra.java  | 118 ++++++++++++++++++++-
 1 file changed, 117 insertions(+), 1 deletion(-)

diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java
index 7adf502..dc1122c 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java
@@ -19,6 +19,9 @@
 
 package org.apache.james.backends.cassandra;
 
+import org.apache.james.backends.cassandra.init.ClusterFactory;
+import org.apache.james.backends.cassandra.init.KeyspaceFactory;
+import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 import org.apache.james.util.Host;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -28,12 +31,110 @@ import org.testcontainers.containers.output.OutputFrame;
 import org.testcontainers.images.builder.ImageFromDockerfile;
 import org.testcontainers.images.builder.dockerfile.DockerfileBuilder;
 
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.schemabuilder.SchemaBuilder;
 import com.github.dockerjava.api.DockerClient;
 import com.google.common.collect.ImmutableMap;
 
 public class DockerCassandra {
 
+    /**
+     * James uses a non privileged Cassandra user(role) in testing. To be able to do that, the non privileged user needs to be
+     * prepared along with a created keyspace.
+     *
+     * This process is done by using the default user provided by docker cassandra, it has the capability of creating roles,
+     * keyspaces, and granting permissions to those entities.
+     */
+    public static class CassandraResourcesManager {
+
+        private static final String CASSANDRA_SUPER_USER = "cassandra";
+        private static final String CASSANDRA_SUPER_USER_PASSWORD = "cassandra";
+
+        private final DockerCassandra cassandra;
+
+        private CassandraResourcesManager(DockerCassandra cassandra) {
+            this.cassandra = cassandra;
+        }
+
+        public void initializeKeyspace(String keyspace) {
+            ClusterConfiguration configuration = configurationBuilder(keyspace).build();
+
+            try (Cluster privilegedCluster = ClusterFactory.create(configuration)) {
+                provisionNonPrivilegedUser(privilegedCluster);
+                KeyspaceFactory.createKeyspace(configuration, privilegedCluster);
+                grantPermissionTestingUser(privilegedCluster, keyspace);
+            }
+        }
+
+        public void dropKeyspace(String keyspace) {
+            try (Cluster cluster = ClusterFactory.create(configurationBuilder(keyspace).build())) {
+                try (Session cassandraSession = cluster.newSession()) {
+                    boolean applied = cassandraSession.execute(
+                        SchemaBuilder.dropKeyspace(keyspace)
+                            .ifExists())
+                        .wasApplied();
+
+                    if (!applied) {
+                        throw new IllegalStateException("cannot drop keyspace '" + keyspace + "'");
+                    }
+                }
+            }
+
+        }
+
+        public boolean keyspaceExist(String keyspace) {
+            try (Cluster cluster = ClusterFactory.create(configurationBuilder(keyspace).build())) {
+                return KeyspaceFactory.keyspaceExist(cluster, keyspace);
+            }
+        }
+
+        private void provisionNonPrivilegedUser(Cluster privilegedCluster) {
+            try (Session session = privilegedCluster.newSession()) {
+                session.execute("CREATE ROLE IF NOT EXISTS " + CASSANDRA_TESTING_USER + " WITH PASSWORD = '" + CASSANDRA_TESTING_PASSWORD + "' AND LOGIN = true");
+            }
+        }
+
+        private void grantPermissionTestingUser(Cluster privilegedCluster, String keyspace) {
+            try (Session session = privilegedCluster.newSession()) {
+                session.execute("GRANT CREATE ON KEYSPACE " + keyspace + " TO " + CASSANDRA_TESTING_USER);
+                session.execute("GRANT SELECT ON KEYSPACE " + keyspace + " TO " + CASSANDRA_TESTING_USER);
+                session.execute("GRANT MODIFY ON KEYSPACE " + keyspace + " TO " + CASSANDRA_TESTING_USER);
+                // some tests require dropping in setups
+                session.execute("GRANT DROP ON KEYSPACE " + keyspace + " TO " + CASSANDRA_TESTING_USER);
+            }
+        }
+
+        private ClusterConfiguration.Builder configurationBuilder(String keyspace) {
+            return ClusterConfiguration.builder()
+                .host(cassandra.getHost())
+                .username(CASSANDRA_SUPER_USER)
+                .password(CASSANDRA_SUPER_USER_PASSWORD)
+                .keyspace(keyspace)
+                .createKeyspace()
+                .disableDurableWrites()
+                .replicationFactor(1)
+                .maxRetry(RELAXED_RETRIES);
+        }
+    }
+
+    public static ClusterConfiguration.Builder configurationBuilder(Host... hosts) {
+        return ClusterConfiguration.builder()
+            .hosts(hosts)
+            .keyspace(KEYSPACE)
+            .username(CASSANDRA_TESTING_USER)
+            .password(CASSANDRA_TESTING_PASSWORD)
+            .disableDurableWrites()
+            .replicationFactor(1)
+            .maxRetry(RELAXED_RETRIES);
+    }
+
     private static final Logger logger = LoggerFactory.getLogger(DockerCassandra.class);
+    private static final String KEYSPACE = "testing";
+    private static final int RELAXED_RETRIES = 2;
+
+    public static final String CASSANDRA_TESTING_USER = "james_testing";
+    public static final String CASSANDRA_TESTING_PASSWORD = "james_testing_password";
 
     @FunctionalInterface
     public interface AdditionalDockerFileStep {
@@ -67,7 +168,9 @@ public class DockerCassandra {
                         .env("ENV CASSANDRA_CONFIG", "/etc/cassandra")
                         .run("echo \"-Xms" + CASSANDRA_MEMORY + "M\" >> " + JVM_OPTIONS)
                         .run("echo \"-Xmx" + CASSANDRA_MEMORY + "M\" >> " + JVM_OPTIONS)
-                        .run("sed", "-i", "s/auto_snapshot: true/auto_snapshot: false/g", "/etc/cassandra/cassandra.yaml"))
+                        .run("sed", "-i", "s/auto_snapshot: true/auto_snapshot: false/g", "/etc/cassandra/cassandra.yaml")
+                        .run("echo 'authenticator: PasswordAuthenticator' >> /etc/cassandra/cassandra.yaml")
+                        .run("echo 'authorizer: org.apache.cassandra.auth.CassandraAuthorizer' >> /etc/cassandra/cassandra.yaml"))
                         .build()))
             .withTmpFs(ImmutableMap.of("/var/lib/cassandra", "rw,noexec,nosuid,size=200m"))
             .withExposedPorts(CASSANDRA_PORT)
@@ -83,9 +186,14 @@ public class DockerCassandra {
     public void start() {
         if (!cassandraContainer.isRunning()) {
             cassandraContainer.start();
+            administrator().initializeKeyspace(KEYSPACE);
         }
     }
 
+    public CassandraResourcesManager administrator() {
+        return new CassandraResourcesManager(this);
+    }
+
     public void stop() {
         if (cassandraContainer.isRunning()) {
             cassandraContainer.stop();
@@ -118,4 +226,12 @@ public class DockerCassandra {
         client.unpauseContainerCmd(cassandraContainer.getContainerId()).exec();
     }
 
+    public ClusterConfiguration.Builder configurationBuilder() {
+        return configurationBuilder(getHost());
+    }
+
+    public ClusterConfiguration.Builder configurationBuilderForSuperUser() {
+        return administrator()
+            .configurationBuilder(KEYSPACE);
+    }
 }


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


[james-project] 23/29: JAMES-2985 JPAMessageMapper should also delete messages not marked as deleted

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 d37340bbd0f406803a1a7c53805e718ff05c7eb7
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Feb 28 10:32:39 2020 +0700

    JAMES-2985 JPAMessageMapper should also delete messages not marked as deleted
---
 .../james/mailbox/jpa/mail/JPAMessageMapper.java   | 96 +++++++++++-----------
 .../model/openjpa/AbstractJPAMailboxMessage.java   |  8 +-
 .../store/mail/model/MessageMapperTest.java        | 13 +++
 3 files changed, 64 insertions(+), 53 deletions(-)

diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java
index 601a731..b1b8f71 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java
@@ -43,6 +43,7 @@ import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMailboxMessage;
 import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAStreamingMailboxMessage;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxCounters;
+import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageRange.Type;
@@ -95,33 +96,30 @@ public class JPAMessageMapper extends JPATransactionalMapper implements MessageM
     @Override
     public Iterator<MailboxMessage> findInMailbox(Mailbox mailbox, MessageRange set, FetchType fType, int max)
             throws MailboxException {
+
+        return findAsList(mailbox.getMailboxId(), set, max).iterator();
+    }
+
+    private List<MailboxMessage> findAsList(MailboxId mailboxId, MessageRange set, int max) throws MailboxException {
         try {
-            List<MailboxMessage> results;
             MessageUid from = set.getUidFrom();
-            final MessageUid to = set.getUidTo();
-            final Type type = set.getType();
-            JPAId mailboxId = (JPAId) mailbox.getMailboxId();
+            MessageUid to = set.getUidTo();
+            Type type = set.getType();
+            JPAId jpaId = (JPAId) mailboxId;
 
             switch (type) {
-            default:
-            case ALL:
-                results = findMessagesInMailbox(mailboxId, max);
-                break;
-            case FROM:
-                results = findMessagesInMailboxAfterUID(mailboxId, from, max);
-                break;
-            case ONE:
-                results = findMessagesInMailboxWithUID(mailboxId, from);
-                break;
-            case RANGE:
-                results = findMessagesInMailboxBetweenUIDs(mailboxId, from, to, max);
-                break;
+                default:
+                case ALL:
+                    return findMessagesInMailbox(jpaId, max);
+                case FROM:
+                    return findMessagesInMailboxAfterUID(jpaId, from, max);
+                case ONE:
+                    return findMessagesInMailboxWithUID(jpaId, from);
+                case RANGE:
+                    return findMessagesInMailboxBetweenUIDs(jpaId, from, to, max);
             }
-
-            return results.iterator();
-
         } catch (PersistenceException e) {
-            throw new MailboxException("Search of MessageRange " + set + " failed in mailbox " + mailbox, e);
+            throw new MailboxException("Search of MessageRange " + set + " failed in mailbox " + mailboxId.serialize(), e);
         }
     }
 
@@ -229,21 +227,6 @@ public class JPAMessageMapper extends JPATransactionalMapper implements MessageM
         }
     }
 
-    @Override
-    public Map<MessageUid, MessageMetaData> deleteMessages(Mailbox mailbox, List<MessageUid> uids) throws MailboxException {
-        JPAId mailboxId = (JPAId) mailbox.getMailboxId();
-        Map<MessageUid, MessageMetaData> data = new HashMap<>();
-        List<MessageRange> ranges = MessageRange.toRanges(uids);
-
-        ranges.forEach(range -> {
-            List<MailboxMessage> messages = findDeletedMessages(range, mailboxId);
-            data.putAll(createMetaData(messages));
-            deleteDeletedMessages(range, mailboxId);
-        });
-
-        return data;
-    }
-
     private List<MailboxMessage> findDeletedMessages(MessageRange messageRange, JPAId mailboxId) {
         MessageUid from = messageRange.getUidFrom();
         MessageUid to = messageRange.getUidTo();
@@ -262,22 +245,37 @@ public class JPAMessageMapper extends JPATransactionalMapper implements MessageM
         }
     }
 
-    private void deleteDeletedMessages(MessageRange messageRange, JPAId mailboxId) {
+    @Override
+    public Map<MessageUid, MessageMetaData> deleteMessages(Mailbox mailbox, List<MessageUid> uids) throws MailboxException {
+        JPAId mailboxId = (JPAId) mailbox.getMailboxId();
+        Map<MessageUid, MessageMetaData> data = new HashMap<>();
+        List<MessageRange> ranges = MessageRange.toRanges(uids);
+
+        ranges.forEach(Throwing.<MessageRange>consumer(range -> {
+            List<MailboxMessage> messages = findAsList(mailboxId, range, JPAMessageMapper.UNLIMITED);
+            data.putAll(createMetaData(messages));
+            deleteMessages(range, mailboxId);
+        }).sneakyThrow());
+
+        return data;
+    }
+
+    private void deleteMessages(MessageRange messageRange, JPAId mailboxId) {
         MessageUid from = messageRange.getUidFrom();
         MessageUid to = messageRange.getUidTo();
 
         switch (messageRange.getType()) {
             case ONE:
-                deleteDeletedMessagesInMailboxWithUID(mailboxId, from);
+                deleteMessagesInMailboxWithUID(mailboxId, from);
                 break;
             case RANGE:
-                deleteDeletedMessagesInMailboxBetweenUIDs(mailboxId, from, to);
+                deleteMessagesInMailboxBetweenUIDs(mailboxId, from, to);
                 break;
             case FROM:
-                deleteDeletedMessagesInMailboxAfterUID(mailboxId, from);
+                deleteMessagesInMailboxAfterUID(mailboxId, from);
                 break;
             case ALL:
-                deleteDeletedMessagesInMailbox(mailboxId);
+                deleteMessagesInMailbox(mailboxId);
                 break;
             default:
                 throw new RuntimeException("Cannot delete messages, range type " + messageRange.getType() + " doesn't exist");
@@ -438,23 +436,23 @@ public class JPAMessageMapper extends JPATransactionalMapper implements MessageM
             .collect(Guavate.toImmutableList());
     }
 
-    private int deleteDeletedMessagesInMailbox(JPAId mailboxId) {
-        return getEntityManager().createNamedQuery("deleteDeletedMessagesInMailbox")
+    private int deleteMessagesInMailbox(JPAId mailboxId) {
+        return getEntityManager().createNamedQuery("deleteMessagesInMailbox")
                 .setParameter("idParam", mailboxId.getRawId()).executeUpdate();
     }
 
-    private int deleteDeletedMessagesInMailboxAfterUID(JPAId mailboxId, MessageUid from) {
-        return getEntityManager().createNamedQuery("deleteDeletedMessagesInMailboxAfterUID")
+    private int deleteMessagesInMailboxAfterUID(JPAId mailboxId, MessageUid from) {
+        return getEntityManager().createNamedQuery("deleteMessagesInMailboxAfterUID")
                 .setParameter("idParam", mailboxId.getRawId()).setParameter("uidParam", from.asLong()).executeUpdate();
     }
 
-    private int deleteDeletedMessagesInMailboxWithUID(JPAId mailboxId, MessageUid from) {
-        return getEntityManager().createNamedQuery("deleteDeletedMessagesInMailboxWithUID")
+    private int deleteMessagesInMailboxWithUID(JPAId mailboxId, MessageUid from) {
+        return getEntityManager().createNamedQuery("deleteMessagesInMailboxWithUID")
                 .setParameter("idParam", mailboxId.getRawId()).setParameter("uidParam", from.asLong()).executeUpdate();
     }
 
-    private int deleteDeletedMessagesInMailboxBetweenUIDs(JPAId mailboxId, MessageUid from, MessageUid to) {
-        return getEntityManager().createNamedQuery("deleteDeletedMessagesInMailboxBetweenUIDs")
+    private int deleteMessagesInMailboxBetweenUIDs(JPAId mailboxId, MessageUid from, MessageUid to) {
+        return getEntityManager().createNamedQuery("deleteMessagesInMailboxBetweenUIDs")
                 .setParameter("idParam", mailboxId.getRawId()).setParameter("fromParam", from.asLong())
                 .setParameter("toParam", to.asLong()).executeUpdate();
     }
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
index 18bcf7c..cfebd40 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
@@ -84,10 +84,10 @@ import com.google.common.base.Objects;
         @NamedQuery(name = "findDeletedMessagesInMailboxWithUID", query = "SELECT message FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam AND message.uid=:uidParam AND message.deleted=TRUE ORDER BY message.uid ASC"),
         @NamedQuery(name = "findDeletedMessagesInMailboxAfterUID", query = "SELECT message FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam AND message.uid>=:uidParam AND message.deleted=TRUE ORDER BY message.uid ASC"),
 
-        @NamedQuery(name = "deleteDeletedMessagesInMailbox", query = "DELETE FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam AND message.deleted=TRUE"),
-        @NamedQuery(name = "deleteDeletedMessagesInMailboxBetweenUIDs", query = "DELETE FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam AND message.uid BETWEEN :fromParam AND :toParam AND message.deleted=TRUE"),
-        @NamedQuery(name = "deleteDeletedMessagesInMailboxWithUID", query = "DELETE FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam AND message.uid=:uidParam AND message.deleted=TRUE"),
-        @NamedQuery(name = "deleteDeletedMessagesInMailboxAfterUID", query = "DELETE FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam AND message.uid>=:uidParam AND message.deleted=TRUE"),
+        @NamedQuery(name = "deleteMessagesInMailbox", query = "DELETE FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam"),
+        @NamedQuery(name = "deleteMessagesInMailboxBetweenUIDs", query = "DELETE FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam AND message.uid BETWEEN :fromParam AND :toParam"),
+        @NamedQuery(name = "deleteMessagesInMailboxWithUID", query = "DELETE FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam AND message.uid=:uidParam"),
+        @NamedQuery(name = "deleteMessagesInMailboxAfterUID", query = "DELETE FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam AND message.uid>=:uidParam"),
 
         @NamedQuery(name = "countUnseenMessagesInMailbox", query = "SELECT COUNT(message) FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam AND message.seen=FALSE"),
         @NamedQuery(name = "countMessagesInMailbox", query = "SELECT COUNT(message) FROM MailboxMessage message WHERE message.mailbox.mailboxId = :idParam"),
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
index bd3b111..14341ee 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
@@ -1162,6 +1162,19 @@ public abstract class MessageMapperTest {
     }
 
     @Test
+    void deleteMessagesShouldNotRequireMessagesToBeMarkedAsDeleted() throws Exception {
+        saveMessages();
+
+        messageMapper.deleteMessages(benwaInboxMailbox, ImmutableList.of(message2.getUid(), message3.getUid()));
+
+        assertThat(messageMapper.listAllMessageUids(benwaInboxMailbox))
+            .toIterable()
+            .containsOnly(message1.getUid(),
+                message4.getUid(),
+                message5.getUid());
+    }
+
+    @Test
     void getUidsShouldNotReturnUidsOfDeletedMessages() throws Exception {
         saveMessages();
 


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


[james-project] 18/29: JAMES-3074 Warn against the usage of UidValidity::of

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 85535741e45aaf717a5cb7fdfc5aef3f3e18b563
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Feb 26 18:09:48 2020 +0700

    JAMES-3074 Warn against the usage of UidValidity::of
---
 .../src/main/java/org/apache/james/mailbox/model/UidValidity.java   | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
index ce6b841..c93cb2a 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
@@ -49,6 +49,12 @@ public class UidValidity {
         return ofValid(sanitizedRandomValue);
     }
 
+    /**
+     * This method allows deserialization of potentially invalid already stored UidValidity, and should only be used for
+     * compatibility purposes.
+     *
+     * Strongly favor uses of  {@link #ofValid(long)}
+     */
     public static UidValidity of(long uidValidity) {
         return new UidValidity(uidValidity);
     }


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


[james-project] 26/29: JAMES-3080 add test to ensure message can survive a rabbitMQ restart

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 fba9579005d91af028dad4db8c9ad7732038b7e1
Author: Rémi KOWALSKI <rk...@linagora.com>
AuthorDate: Fri Feb 28 17:39:08 2020 +0100

    JAMES-3080 add test to ensure message can survive a rabbitMQ restart
---
 .../apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java   | 1 +
 1 file changed, 1 insertion(+)

diff --git a/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java b/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
index d91d786..24ab254 100644
--- a/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
+++ b/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
@@ -40,6 +40,7 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableMap;
 import com.rabbitmq.client.AMQP;
 import com.rabbitmq.client.Delivery;
+
 import reactor.core.Disposable;
 import reactor.core.publisher.Mono;
 import reactor.core.publisher.UnicastProcessor;


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


[james-project] 01/29: MAILBOX-396 Some reactor improvement in CassandraMessageMapper

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 9a1d36b71c1b6af7cc3a71b7635c6f32f5f7e5f7
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Feb 7 14:14:58 2020 +0700

    MAILBOX-396 Some reactor improvement in CassandraMessageMapper
    
    Avoid calling several time 'block' upon `add`, `setInMailboxes`, `findInMailbox`
---
 .../cassandra/mail/CassandraMessageMapper.java     | 44 ++++++++++++----------
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 695c38f..7fc68f1 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -171,17 +171,17 @@ public class CassandraMessageMapper implements MessageMapper {
     @Override
     public Iterator<MailboxMessage> findInMailbox(Mailbox mailbox, MessageRange messageRange, FetchType ftype, int max) {
         CassandraId mailboxId = (CassandraId) mailbox.getMailboxId();
-        return retrieveMessages(retrieveMessageIds(mailboxId, messageRange), ftype, Limit.from(max))
+        return retrieveMessageIds(mailboxId, messageRange)
+            .flatMapMany(ids -> retrieveMessages(ids, ftype, Limit.from(max)))
             .map(MailboxMessage.class::cast)
             .sort(Comparator.comparing(MailboxMessage::getUid))
             .toIterable()
             .iterator();
     }
 
-    private List<ComposedMessageIdWithMetaData> retrieveMessageIds(CassandraId mailboxId, MessageRange messageRange) {
+    private Mono<List<ComposedMessageIdWithMetaData>> retrieveMessageIds(CassandraId mailboxId, MessageRange messageRange) {
         return messageIdDAO.retrieveMessages(mailboxId, messageRange)
-            .collect(Guavate.toImmutableList())
-            .block();
+            .collect(Guavate.toImmutableList());
     }
 
     private Flux<MailboxMessage> retrieveMessages(List<ComposedMessageIdWithMetaData> messageIds, FetchType fetchType, Limit limit) {
@@ -267,13 +267,15 @@ public class CassandraMessageMapper implements MessageMapper {
     public MessageMetaData add(Mailbox mailbox, MailboxMessage message) throws MailboxException {
         CassandraId mailboxId = (CassandraId) mailbox.getMailboxId();
 
-        save(mailbox, addUidAndModseq(message, mailboxId))
-            .thenEmpty(indexTableHandler.updateIndexOnAdd(message, mailboxId))
-            .block();
-        return message.metaData();
+        return block(addUidAndModseq(message, mailboxId)
+            .flatMap(Throwing.function(messageWithUidAndModSeq -> save(mailbox, messageWithUidAndModSeq)
+                .thenReturn(messageWithUidAndModSeq)))
+            .flatMap(messageWithUidAndModSeq -> indexTableHandler.updateIndexOnAdd(message, mailboxId)
+                .thenReturn(messageWithUidAndModSeq))
+            .map(MailboxMessage::metaData));
     }
 
-    private MailboxMessage addUidAndModseq(MailboxMessage message, CassandraId mailboxId) throws MailboxException {
+    private Mono<MailboxMessage> addUidAndModseq(MailboxMessage message, CassandraId mailboxId) {
         Mono<MessageUid> messageUidMono = uidProvider
             .nextUid(mailboxId)
             .switchIfEmpty(Mono.error(() -> new MailboxException("Can not find a UID to save " + message.getMessageId() + " in " + mailboxId)));
@@ -281,20 +283,23 @@ public class CassandraMessageMapper implements MessageMapper {
         Mono<ModSeq> nextModSeqMono = modSeqProvider.nextModSeq(mailboxId)
             .switchIfEmpty(Mono.error(() -> new MailboxException("Can not find a MODSEQ to save " + message.getMessageId() + " in " + mailboxId)));
 
-        try {
-            Mono.zip(messageUidMono, nextModSeqMono)
+        return Mono.zip(messageUidMono, nextModSeqMono)
                 .doOnNext(tuple -> {
                     message.setUid(tuple.getT1());
                     message.setModSeq(tuple.getT2());
                 })
-                .block();
+                .thenReturn(message);
+    }
+
+    private <T> T block(Mono<T> mono) throws MailboxException {
+        try {
+            return mono.block();
         } catch (RuntimeException e) {
             if (e.getCause() instanceof MailboxException) {
-                throw (MailboxException)e.getCause();
+                throw (MailboxException) e.getCause();
             }
             throw e;
         }
-        return message;
     }
 
     @Override
@@ -384,11 +389,12 @@ public class CassandraMessageMapper implements MessageMapper {
 
     private MessageMetaData setInMailbox(Mailbox mailbox, MailboxMessage message) throws MailboxException {
         CassandraId mailboxId = (CassandraId) mailbox.getMailboxId();
-
-        insertIds(addUidAndModseq(message, mailboxId), mailboxId)
-                .thenEmpty(indexTableHandler.updateIndexOnAdd(message, mailboxId))
-                .block();
-        return message.metaData();
+        return block(addUidAndModseq(message, mailboxId)
+            .flatMap(messageWithUidAndModseq -> insertIds(messageWithUidAndModseq, mailboxId)
+                .thenReturn(messageWithUidAndModseq))
+            .flatMap(messageWithUidAndModseq -> indexTableHandler.updateIndexOnAdd(message, mailboxId)
+                .thenReturn(messageWithUidAndModseq))
+            .map(MailboxMessage::metaData));
     }
 
     private Mono<Void> save(Mailbox mailbox, MailboxMessage message) throws MailboxException {


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


[james-project] 27/29: JAMES-3080 set persistent delivery mode when submiting message to the rabbit workqueue

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 7fa917f763b1e0a112808cd07f6b36d448432fd4
Author: Rémi KOWALSKI <rk...@linagora.com>
AuthorDate: Fri Feb 28 15:59:28 2020 +0100

    JAMES-3080 set persistent delivery mode when submiting message to the rabbit workqueue
---
 .../james/task/eventsourcing/distributed/RabbitMQWorkQueue.java     | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java b/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
index 24ab254..4b57d53 100644
--- a/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
+++ b/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
@@ -20,6 +20,8 @@
 
 package org.apache.james.task.eventsourcing.distributed;
 
+import static com.rabbitmq.client.MessageProperties.PERSISTENT_TEXT_PLAIN;
+
 import java.nio.charset.StandardCharsets;
 import java.util.Optional;
 import java.util.UUID;
@@ -185,8 +187,12 @@ public class RabbitMQWorkQueue implements WorkQueue {
         try {
             byte[] payload = taskSerializer.serialize(taskWithId.getTask()).getBytes(StandardCharsets.UTF_8);
             AMQP.BasicProperties basicProperties = new AMQP.BasicProperties.Builder()
+                .deliveryMode(PERSISTENT_TEXT_PLAIN.getDeliveryMode())
+                .priority(PERSISTENT_TEXT_PLAIN.getPriority())
+                .contentType(PERSISTENT_TEXT_PLAIN.getContentType())
                 .headers(ImmutableMap.of(TASK_ID, taskWithId.getId().asString()))
                 .build();
+
             OutboundMessage outboundMessage = new OutboundMessage(EXCHANGE_NAME, ROUTING_KEY, basicProperties, payload);
             channelPool.getSender().send(Mono.just(outboundMessage)).block();
         } catch (JsonProcessingException e) {


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


[james-project] 13/29: JAMES−3074 Create UidValidity type

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 e9556525d79dbf8a6611080acd3dd1a8881ba70f
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu Feb 20 15:58:07 2020 +0700

    JAMES−3074 Create UidValidity type
---
 .../apache/james/mailbox/model/UidValidity.java    | 61 ++++++++++++++++++++++
 .../james/mailbox/model/UidValidityTest.java       | 41 +++++++++++++++
 2 files changed, 102 insertions(+)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
new file mode 100644
index 0000000..646b43c
--- /dev/null
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
@@ -0,0 +1,61 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.model;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+public class UidValidity {
+    public static UidValidity of(long uidValidity) {
+        return new UidValidity(uidValidity);
+    }
+
+    private final long uidValidity;
+
+    private UidValidity(long uidValidity) {
+        this.uidValidity = uidValidity;
+    }
+
+    public long asLong() {
+        return uidValidity;
+    }
+
+    @Override
+    public final boolean equals(Object obj) {
+        if (obj instanceof UidValidity) {
+            UidValidity other = (UidValidity) obj;
+            return Objects.equal(uidValidity, other.uidValidity);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hashCode(uidValidity);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects
+            .toStringHelper(this)
+            .add("uidValidity", uidValidity)
+            .toString();
+    }
+}
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java
new file mode 100644
index 0000000..a77e074
--- /dev/null
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java
@@ -0,0 +1,41 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+class UidValidityTest {
+    @Test
+    void shouldRespectBeanContract() {
+        EqualsVerifier.forClass(UidValidity.class)
+            .verify();
+    }
+
+    @Test
+    void ofShouldReturnValidUidValidity() {
+        long expectedValue = 123456789L;
+        UidValidity uidValidity = UidValidity.of(expectedValue);
+        assertThat(uidValidity.asLong()).isEqualTo(expectedValue);
+    }
+}


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


[james-project] 11/29: JAMES-3061 Simplify FixingGhostMailboxTest setup

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 9d9edcd8a820446f54d00db013051c83345eb0a9
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Tue Feb 25 17:10:08 2020 +0700

    JAMES-3061 Simplify FixingGhostMailboxTest setup
---
 .../org/apache/james/server/CassandraProbe.java    |  4 ++--
 .../java/org/apache/james/CassandraExtension.java  | 24 ----------------------
 .../rabbitmq/FixingGhostMailboxTest.java           | 23 +++++++++------------
 3 files changed, 12 insertions(+), 39 deletions(-)

diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/server/CassandraProbe.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/server/CassandraProbe.java
index 8bb6952..6483b16 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/server/CassandraProbe.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/server/CassandraProbe.java
@@ -32,7 +32,7 @@ public class CassandraProbe implements GuiceProbe {
         this.clusterConfiguration = configuration;
     }
 
-    public String getKeyspace() {
-        return clusterConfiguration.getKeyspace();
+    public ClusterConfiguration getConfiguration() {
+        return clusterConfiguration;
     }
 }
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
index 2532c49..7808923 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
@@ -19,25 +19,12 @@
 
 package org.apache.james;
 
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.apache.james.util.Host;
 import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.jupiter.api.extension.ParameterContext;
-import org.junit.jupiter.api.extension.ParameterResolutionException;
 
 import com.google.inject.Module;
 
 public class CassandraExtension implements GuiceModuleTestExtension {
 
-    @Target(ElementType.PARAMETER)
-    @Retention(RetentionPolicy.RUNTIME)
-    public @interface CassandraHost {
-    }
-
     private final DockerCassandraRule cassandra;
 
     public CassandraExtension() {
@@ -70,15 +57,4 @@ public class CassandraExtension implements GuiceModuleTestExtension {
     public void unpause() {
         cassandra.unpause();
     }
-
-    @Override
-    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
-        return parameterContext.getParameter().getType() == Host.class
-            && parameterContext.getParameter().isAnnotationPresent(CassandraHost.class);
-    }
-
-    @Override
-    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
-        return cassandra.getHost();
-    }
 }
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/FixingGhostMailboxTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/FixingGhostMailboxTest.java
index 87529d2..49685df 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/FixingGhostMailboxTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/FixingGhostMailboxTest.java
@@ -43,12 +43,13 @@ import java.nio.charset.StandardCharsets;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.james.CassandraExtension;
-import org.apache.james.CassandraExtension.CassandraHost;
 import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
+import org.apache.james.backends.cassandra.init.ClusterFactory;
+import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 import org.apache.james.core.Username;
 import org.apache.james.jmap.AccessToken;
 import org.apache.james.jmap.draft.JmapGuiceProbe;
@@ -71,7 +72,6 @@ import org.apache.james.modules.RabbitMQExtension;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.server.CassandraProbe;
 import org.apache.james.task.TaskManager;
-import org.apache.james.util.Host;
 import org.apache.james.util.Port;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.WebAdminGuiceProbe;
@@ -122,7 +122,6 @@ class FixingGhostMailboxTest {
     private AccessToken accessToken;
     private MailboxProbeImpl mailboxProbe;
     private ACLProbe aclProbe;
-    private Session session;
     private ComposedMessageId message1;
     private MailboxId aliceGhostInboxId;
     private MailboxPath aliceInboxPath;
@@ -130,7 +129,7 @@ class FixingGhostMailboxTest {
     private RequestSpecification webadminSpecification;
 
     @BeforeEach
-    void setup(GuiceJamesServer server, @CassandraHost Host cassandraHost) throws Throwable {
+    void setup(GuiceJamesServer server) throws Throwable {
         WebAdminGuiceProbe webAdminProbe = server.getProbe(WebAdminGuiceProbe.class);
         mailboxProbe = server.getProbe(MailboxProbeImpl.class);
         aclProbe = server.getProbe(ACLProbeImpl.class);
@@ -152,17 +151,15 @@ class FixingGhostMailboxTest {
             .addUser(BOB, BOB_SECRET);
         accessToken = authenticateJamesUser(baseUri(jmapPort), Username.of(ALICE), ALICE_SECRET);
 
-        session = Cluster.builder()
-            .withoutJMXReporting()
-            .addContactPoint(cassandraHost.getHostName())
-            .withPort(cassandraHost.getPort())
-            .build()
-            .connect(server.getProbe(CassandraProbe.class).getKeyspace());
-
-        simulateGhostMailboxBug();
+        ClusterConfiguration cassandraConfiguration = server.getProbe(CassandraProbe.class).getConfiguration();
+        try (Cluster cluster = ClusterFactory.create(cassandraConfiguration)) {
+            try (Session session = cluster.connect(cassandraConfiguration.getKeyspace())) {
+                simulateGhostMailboxBug(session);
+            }
+        }
     }
 
-    private void simulateGhostMailboxBug() throws MailboxException, IOException {
+    private void simulateGhostMailboxBug(Session session) throws MailboxException, IOException {
         // State before ghost mailbox bug
         // Alice INBOX is delegated to Bob and contains one message
         aliceInboxPath = MailboxPath.inbox(Username.of(ALICE));


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


[james-project] 15/29: JAMES-3057 MaildirFolder should not rely on an invalid UidValidity

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 cd2d2a80cd1ec151ab9f6dc581c47f6a74e4fddd
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Feb 26 11:07:20 2020 +0700

    JAMES-3057 MaildirFolder should not rely on an invalid UidValidity
    
    Using Optional is a better pattern for representing a not-yet-known value.
---
 .../java/org/apache/james/mailbox/maildir/MaildirFolder.java  | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
index 2f4418e..efad990 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
@@ -59,7 +59,6 @@ import org.slf4j.LoggerFactory;
 
 public class MaildirFolder {
     private static final Logger LOGGER = LoggerFactory.getLogger(MaildirFolder.class);
-    private static final UidValidity DEFAULT_UID_VALIDITY = UidValidity.of(-1);
 
     public static final String VALIDITY_FILE = "james-uidvalidity";
     public static final String UIDLIST_FILE = "james-uidlist";
@@ -79,7 +78,7 @@ public class MaildirFolder {
 
     private Optional<MessageUid> lastUid;
     private int messageCount = 0;
-    private UidValidity uidValidity = DEFAULT_UID_VALIDITY;
+    private Optional<UidValidity> uidValidity = Optional.empty();
     private MailboxACL acl;
     private boolean messageNameStrictParse = false;
 
@@ -252,10 +251,10 @@ public class MaildirFolder {
      * @return The uidValidity
      */
     public UidValidity getUidValidity() throws IOException {
-        if (uidValidity.equals(DEFAULT_UID_VALIDITY)) {
-            uidValidity = readUidValidity();
+        if (!uidValidity.isPresent()) {
+            uidValidity = Optional.of(readUidValidity());
         }
-        return uidValidity;
+        return uidValidity.get();
     }
     
     /**
@@ -263,7 +262,7 @@ public class MaildirFolder {
      */
     public void setUidValidity(UidValidity uidValidity) throws IOException {
         saveUidValidity(uidValidity);
-        this.uidValidity = uidValidity;
+        this.uidValidity = Optional.of(uidValidity);
     }
 
     /**


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


[james-project] 20/29: JAMES-3075 prove that CassandraIndexTableHandler don't handle errors gracefully

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 7b3ba54d0389b2496b25ab197546c2dd075fcb68
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Feb 27 14:56:28 2020 +0700

    JAMES-3075 prove that CassandraIndexTableHandler don't handle errors gracefully
---
 .../mail/CassandraIndexTableHandlerTest.java       | 31 ++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
index ad0f2be..6259819 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.mailbox.cassandra.mail;
 
+import static org.apache.james.backends.cassandra.Scenario.Builder.fail;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -46,11 +47,16 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.UpdatedFlags;
+import org.apache.james.mailbox.store.MessageBuilder;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
+import reactor.core.publisher.Mono;
+
 class CassandraIndexTableHandlerTest {
 
     private static final CassandraId MAILBOX_ID = CassandraId.timeBased();
@@ -95,6 +101,31 @@ class CassandraIndexTableHandlerTest {
             MAILBOX_ID);
     }
 
+    @Nested
+    class Failures {
+        @Disabled("JAMES-3075 prove that CassandraIndexTableHandler don't handle errors gracefully")
+        @Test
+        void messageCountShouldBeUpdatedUponDeletedMessageFailure(CassandraCluster cassandra) throws Exception {
+            MailboxMessage message = new MessageBuilder()
+                .flags(FlagsBuilder.builder()
+                    .add(Flags.Flag.DELETED, Flags.Flag.RECENT)
+                    .add("customFlag")
+                    .build())
+                .build();
+
+            cassandra.getConf().registerScenario(fail()
+                .times(1)
+                .whenQueryStartsWith("INSERT INTO messageDeleted (mailboxId,uid) VALUES (:mailboxId,:uid);"));
+
+            testee.updateIndexOnAdd(message, MAILBOX_ID)
+                .onErrorResume(any -> Mono.empty())
+                .block();
+
+            Long actual = mailboxCounterDAO.countMessagesInMailbox(mailbox).block();
+            assertThat(actual).isEqualTo(1);
+        }
+    }
+
     @Test
     void updateIndexOnAddShouldIncrementMessageCount() throws Exception {
         MailboxMessage message = mock(MailboxMessage.class);


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


[james-project] 25/29: JAMES-3080 add test to ensure message can survive a rabbitMQ restart

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 8e8775943e4d64e74e37cbfddfaa4ead1948e122
Author: Rémi KOWALSKI <rk...@linagora.com>
AuthorDate: Fri Feb 28 15:44:44 2020 +0100

    JAMES-3080 add test to ensure message can survive a rabbitMQ restart
---
 .../distributed/RabbitMQWorkQueue.java             |  10 +-
 .../RabbitMQWorkQueuePersistenceTest.java          | 109 +++++++++++++++++++++
 2 files changed, 116 insertions(+), 3 deletions(-)

diff --git a/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java b/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
index eb2044d..d91d786 100644
--- a/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
+++ b/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
@@ -36,10 +36,10 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableMap;
 import com.rabbitmq.client.AMQP;
 import com.rabbitmq.client.Delivery;
-
 import reactor.core.Disposable;
 import reactor.core.publisher.Mono;
 import reactor.core.publisher.UnicastProcessor;
@@ -93,11 +93,15 @@ public class RabbitMQWorkQueue implements WorkQueue {
     }
 
     private void startWorkqueue() {
+        declareQueue();
+        consumeWorkqueue();
+    }
+
+    @VisibleForTesting
+    void declareQueue() {
         channelPool.getSender().declareExchange(ExchangeSpecification.exchange(EXCHANGE_NAME)).block();
         channelPool.getSender().declare(QueueSpecification.queue(QUEUE_NAME).durable(true).arguments(Constants.WITH_SINGLE_ACTIVE_CONSUMER)).block();
         channelPool.getSender().bind(BindingSpecification.binding(EXCHANGE_NAME, ROUTING_KEY, QUEUE_NAME)).block();
-
-        consumeWorkqueue();
     }
 
     private void consumeWorkqueue() {
diff --git a/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueuePersistenceTest.java b/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueuePersistenceTest.java
new file mode 100644
index 0000000..b83bf6f
--- /dev/null
+++ b/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueuePersistenceTest.java
@@ -0,0 +1,109 @@
+/**
+ * *************************************************************
+ * 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.task.eventsourcing.distributed;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+import static org.awaitility.Duration.FIVE_HUNDRED_MILLISECONDS;
+import static org.awaitility.Duration.FIVE_SECONDS;
+import static org.mockito.Mockito.spy;
+
+import org.apache.james.backends.rabbitmq.RabbitMQExtension;
+import org.apache.james.server.task.json.JsonTaskSerializer;
+import org.apache.james.server.task.json.dto.MemoryReferenceTaskStore;
+import org.apache.james.server.task.json.dto.TestTaskDTOModules;
+import org.apache.james.task.MemoryReferenceTask;
+import org.apache.james.task.Task;
+import org.apache.james.task.TaskId;
+import org.apache.james.task.TaskWithId;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class RabbitMQWorkQueuePersistenceTest {
+    private static final TaskId TASK_ID = TaskId.fromString("2c7f4081-aa30-11e9-bf6c-2d3b9e84aafd");
+
+    @RegisterExtension
+    RabbitMQExtension rabbitMQExtension = RabbitMQExtension.defaultRabbitMQ()
+        .restartPolicy(RabbitMQExtension.DockerRestartPolicy.PER_TEST);
+
+    private RabbitMQWorkQueue testee;
+    private ImmediateWorker worker;
+    private JsonTaskSerializer serializer;
+
+    @BeforeEach
+    void setUp() {
+        worker = spy(new ImmediateWorker());
+        serializer = JsonTaskSerializer.of(TestTaskDTOModules.COMPLETED_TASK_MODULE, TestTaskDTOModules.MEMORY_REFERENCE_TASK_MODULE.apply(new MemoryReferenceTaskStore()));
+        testee = new RabbitMQWorkQueue(worker, rabbitMQExtension.getRabbitChannelPool(), serializer);
+        //declare the queue but do not start consuming from it
+        testee.declareQueue();
+    }
+
+    @AfterEach
+    void tearDown() {
+        testee.close();
+    }
+
+    /**
+     * submit on a workqueue which do not consume
+     * restart rabbit
+     * start a workqueue which consume messages
+     * verify that the message is treated
+     */
+    @Disabled("JAMES-3080 rabbitMQ messages need to be persisted")
+    @Test
+    void submittedMessageShouldSurviveRabbitMQRestart() throws Exception {
+        Task TASK = new MemoryReferenceTask(() -> Task.Result.COMPLETED);
+
+        TaskWithId TASK_WITH_ID = new TaskWithId(TASK_ID, TASK);
+
+        testee.submit(TASK_WITH_ID);
+
+        //wait for submit to be effective
+        Thread.sleep(500);
+        testee.close();
+
+        restartRabbitMQ();
+
+        startNewWorkqueue();
+
+        await().atMost(FIVE_HUNDRED_MILLISECONDS).until(() -> !worker.results.isEmpty());
+
+        assertThat(worker.tasks).containsExactly(TASK_WITH_ID);
+        assertThat(worker.results).containsExactly(Task.Result.COMPLETED);
+    }
+
+    private void startNewWorkqueue() {
+        worker = spy(new ImmediateWorker());
+        testee = new RabbitMQWorkQueue(worker, rabbitMQExtension.getRabbitChannelPool(), serializer);
+        testee.start();
+    }
+
+    private void restartRabbitMQ() throws Exception {
+        rabbitMQExtension.getRabbitMQ().stopApp();
+        rabbitMQExtension.getRabbitMQ().startApp();
+        //wait until healthcheck is ok
+        await().atMost(FIVE_SECONDS).until(() -> rabbitMQExtension.managementAPI().listQueues().size() > 0);
+        rabbitMQExtension.getRabbitChannelPool().start();
+    }
+}


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


[james-project] 16/29: JAMES-3074 Generate valid, random based UidValidity

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 014887097decf35bbb34aca694bb46c001cd861b
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Feb 26 11:29:22 2020 +0700

    JAMES-3074 Generate valid, random based UidValidity
    
     - store generation trivialy lead to invalid value on `0` (edge case)
     - maildir being based on a timestamp was generating too large values
    
     Currently allocated values CAN be invalid, but at the very least we
     should stop generating invalid values.
    
     Regarding the choice to be random based:
    
     Despite RFC-3501 recommendations, we chose random as a UidVality
     generation mechanism. Timestamp base approach can lead to UidValidity
     being the same for two mailboxes simultaneously generated, leading
    to some IMPA clients not being able to detect changes.
    
    See https://issues.apache.org/jira/browse/JAMES-3074 for details
---
 .../apache/james/mailbox/model/UidValidity.java    | 46 +++++++++++++
 .../james/mailbox/model/UidValidityTest.java       | 80 ++++++++++++++++++++++
 .../james/mailbox/maildir/MaildirFolder.java       |  7 +-
 .../james/mailbox/store/StoreMailboxManager.java   | 11 +--
 4 files changed, 130 insertions(+), 14 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
index 646b43c..ce6b841 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UidValidity.java
@@ -19,20 +19,66 @@
 
 package org.apache.james.mailbox.model;
 
+import java.security.SecureRandom;
+import java.util.function.Supplier;
+
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
 
 public class UidValidity {
+    private static final SecureRandom RANDOM = new SecureRandom();
+    private static final long UPPER_EXCLUSIVE_BOUND = 1L << 32;
+
+    /**
+     * Despite RFC-3501 recommendations, we chose random as a UidVality generation mechanism.
+     * Timestamp base approach can lead to UidValidity being the same for two mailboxes simultaneously generated, leading
+     * to some IMPA clients not being able to detect changes.
+     *
+     * See https://issues.apache.org/jira/browse/JAMES-3074 for details
+     */
+    public static  UidValidity random() {
+        return fromSupplier(RANDOM::nextLong);
+    }
+
+    @VisibleForTesting
+    static UidValidity fromSupplier(Supplier<Long> longSupplier) {
+        long randomValue = Math.abs(longSupplier.get());
+        long sanitizedRandomValue = 1 + (randomValue % (UPPER_EXCLUSIVE_BOUND - 1));
+        return ofValid(sanitizedRandomValue);
+    }
+
     public static UidValidity of(long uidValidity) {
         return new UidValidity(uidValidity);
     }
 
+    public static UidValidity ofValid(long uidValidity) {
+        Preconditions.checkArgument(isValid(uidValidity), "uidValidity needs to be a non-zero unsigned 32-bit integer");
+        return new UidValidity(uidValidity);
+    }
+
+    private static boolean isValid(long uidValidityAsLong) {
+        return uidValidityAsLong > 0 && uidValidityAsLong < UPPER_EXCLUSIVE_BOUND;
+    }
+
     private final long uidValidity;
 
     private UidValidity(long uidValidity) {
         this.uidValidity = uidValidity;
     }
 
+    public boolean isValid() {
+        // RFC-3501 section
+        /*
+        nz-number       = digit-nz *DIGIT
+                    ; Non-zero unsigned 32-bit integer
+                    ; (0 < n < 4,294,967,296)
+         */
+        return isValid(uidValidity);
+    }
+
+
     public long asLong() {
         return uidValidity;
     }
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java
index a77e074..f48c527 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/UidValidityTest.java
@@ -20,7 +20,12 @@
 package org.apache.james.mailbox.model;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
 
+import java.util.stream.IntStream;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.RepeatedTest;
 import org.junit.jupiter.api.Test;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
@@ -38,4 +43,79 @@ class UidValidityTest {
         UidValidity uidValidity = UidValidity.of(expectedValue);
         assertThat(uidValidity.asLong()).isEqualTo(expectedValue);
     }
+
+    @Test
+    void zeroUidValidityShouldBeInvalid() {
+        assertThat(UidValidity.of(0).isValid()).isFalse();
+    }
+
+    @Test
+    void negativeUidValidityShouldBeInvalid() {
+        assertThat(UidValidity.of(-1).isValid()).isFalse();
+    }
+
+    @Test
+    void tooBigUidValidityShouldBeInvalid() {
+        assertThat(UidValidity.of(4294967296L).isValid()).isFalse();
+    }
+
+    @Test
+    void idValidityShouldBeValid() {
+        assertThat(UidValidity.of(42).isValid()).isTrue();
+    }
+
+    @Test
+    void fromSupplierShouldNotThrowWhenZeroIsGenerated() {
+        assertThatCode(() -> UidValidity.fromSupplier(() -> 0L))
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    void fromSupplierShouldNotThrowWhenNegativeIsGenerated() {
+        assertThatCode(() -> UidValidity.fromSupplier(() -> -42L))
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    void fromSupplierShouldNotThrowWhenUpperBoundExclusiveIsGenerated() {
+        assertThatCode(() -> UidValidity.fromSupplier(() -> 4294967296L))
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    void fromSupplierShouldNotThrowWhenUpperBoundInclusiveIsGenerated() {
+        assertThatCode(() -> UidValidity.fromSupplier(() -> 4294967295L))
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    void fromSupplierShouldNotThrowWhenHigherThanUpperBoundIsGenerated() {
+        assertThatCode(() -> UidValidity.fromSupplier(() -> 4294967297L))
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    void fromSupplierShouldNotThrowWhenLowerThanUpperBoundIsGenerated() {
+        assertThatCode(() -> UidValidity.fromSupplier(() -> 4294967294L))
+            .doesNotThrowAnyException();
+    }
+
+    // Sampling test
+    @RepeatedTest(10000)
+    void randomShouldGenerateValidValues() {
+        assertThatCode(UidValidity::random)
+            .doesNotThrowAnyException();
+    }
+
+    @Disabled("On average upon generating 1.000.000 UidValidity we notice 125 duplicates")
+    @Test
+    void randomShouldNotLeadToCollision() {
+        int count = 1000000;
+        long distinctCount = IntStream.range(0, count)
+            .mapToObj(any -> UidValidity.random())
+            .distinct()
+            .count();
+
+        assertThat(distinctCount).isEqualTo(count);
+    }
 }
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
index efad990..ac8432f 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
@@ -341,10 +341,9 @@ public class MaildirFolder {
      * @return the new uidValidity
      */
     private UidValidity resetUidValidity() throws IOException {
-        // using the timestamp as uidValidity
-        UidValidity timestamp = UidValidity.of(System.currentTimeMillis());
-        setUidValidity(timestamp);
-        return timestamp;
+        UidValidity uidValidity = UidValidity.random();
+        setUidValidity(uidValidity);
+        return uidValidity;
     }
     
     /**
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 6e61512..e7cd367 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
@@ -21,7 +21,6 @@ package org.apache.james.mailbox.store;
 
 import static org.apache.james.mailbox.store.mail.AbstractMessageMapper.UNLIMITED;
 
-import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.EnumSet;
@@ -106,7 +105,6 @@ public class StoreMailboxManager implements MailboxManager {
     private static final Logger LOGGER = LoggerFactory.getLogger(StoreMailboxManager.class);
     public static final char SQL_WILDCARD_CHAR = '%';
     public static final EnumSet<MessageCapabilities> DEFAULT_NO_MESSAGE_CAPABILITIES = EnumSet.noneOf(MessageCapabilities.class);
-    private static final SecureRandom RANDOM = new SecureRandom();
 
     private final StoreRightManager storeRightManager;
     private final EventBus eventBus;
@@ -215,13 +213,6 @@ public class StoreMailboxManager implements MailboxManager {
         return preDeletionHooks;
     }
 
-    /**
-     * Generate and return the next uid validity
-     */
-    protected UidValidity randomUidValidity() {
-        return UidValidity.of(Math.abs(RANDOM.nextInt()));
-    }
-
     @Override
     public MailboxSession createSystemSession(Username userName) {
         return sessionProvider.createSystemSession(userName);
@@ -382,7 +373,7 @@ public class StoreMailboxManager implements MailboxManager {
                 MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(mailboxSession);
                 try {
                     mapper.execute(Mapper.toTransaction(() -> {
-                        Mailbox mailbox = mapper.create(mailboxPath, randomUidValidity());
+                        Mailbox mailbox = mapper.create(mailboxPath, UidValidity.random());
                         mailboxIds.add(mailbox.getMailboxId());
                         // notify listeners
                         eventBus.dispatch(EventFactory.mailboxAdded()


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


[james-project] 06/29: JAMES-3061 Moving the `key space creations` duty to the DockerCassandra

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 079bd0282aad8dc02c6462cac26ba482aa034505
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Mon Feb 24 18:13:07 2020 +0700

    JAMES-3061 Moving the `key space creations` duty to the DockerCassandra
    
    It's now only providing non privileged resources
---
 .../james/backends/cassandra/CassandraCluster.java | 51 +++++++++-------------
 1 file changed, 21 insertions(+), 30 deletions(-)

diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraCluster.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraCluster.java
index 8df9d59..91c61ad 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraCluster.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraCluster.java
@@ -26,7 +26,6 @@ import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.init.CassandraTableManager;
 import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
 import org.apache.james.backends.cassandra.init.ClusterFactory;
-import org.apache.james.backends.cassandra.init.KeyspaceFactory;
 import org.apache.james.backends.cassandra.init.SessionWithInitializedTablesFactory;
 import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
 import org.apache.james.util.Host;
@@ -34,13 +33,6 @@ import org.apache.james.util.Host;
 import com.datastax.driver.core.Cluster;
 
 public final class CassandraCluster implements AutoCloseable {
-    public static final String KEYSPACE = "testing";
-
-    private static Optional<Exception> startStackTrace = Optional.empty();
-    private final CassandraModule module;
-    private TestingSession session;
-    private CassandraTypesProvider typesProvider;
-    private Cluster cluster;
 
     public static CassandraCluster create(CassandraModule module, Host host) {
         assertClusterNotRunning();
@@ -55,27 +47,26 @@ public final class CassandraCluster implements AutoCloseable {
       });
     }
 
+    private static Optional<Exception> startStackTrace = Optional.empty();
+
+    private final CassandraModule module;
+    private final Cluster nonPrivilegedCluster;
+    private final TestingSession nonPrivilegedSession;
+    private final CassandraTypesProvider typesProvider;
+
     private CassandraCluster(CassandraModule module, Host host) throws RuntimeException {
         this.module = module;
-        try {
-            ClusterConfiguration clusterConfiguration = ClusterConfiguration.builder()
-                .host(host)
-                .keyspace(KEYSPACE)
-                .createKeyspace()
-                .disableDurableWrites()
-                .build();
-            cluster = ClusterFactory.create(clusterConfiguration);
-            KeyspaceFactory.createKeyspace(clusterConfiguration, cluster);
-            session = new TestingSession(
-                new SessionWithInitializedTablesFactory(clusterConfiguration, cluster, module).get());
-            typesProvider = new CassandraTypesProvider(module, session);
-        } catch (Exception exception) {
-            throw new RuntimeException(exception);
-        }
+
+        ClusterConfiguration configuration = DockerCassandra.configurationBuilder(host)
+            .build();
+        this.nonPrivilegedCluster = ClusterFactory.create(configuration);
+        this.nonPrivilegedSession = new TestingSession(new SessionWithInitializedTablesFactory(configuration,
+            nonPrivilegedCluster, module).get());
+        this.typesProvider = new CassandraTypesProvider(module, nonPrivilegedSession);
     }
 
     public TestingSession getConf() {
-        return session;
+        return nonPrivilegedSession;
     }
 
     public CassandraTypesProvider getTypesProvider() {
@@ -84,19 +75,19 @@ public final class CassandraCluster implements AutoCloseable {
 
     @Override
     public void close() {
-        session.registerScenario(NOTHING);
-        if (!cluster.isClosed()) {
+        nonPrivilegedSession.registerScenario(NOTHING);
+        if (!nonPrivilegedCluster.isClosed()) {
             clearTables();
             closeCluster();
         }
     }
 
-    public void closeCluster() {
-        cluster.closeAsync().force();
+    void closeCluster() {
+        nonPrivilegedCluster.closeAsync().force();
         startStackTrace = Optional.empty();
     }
 
-    public void clearTables() {
-        new CassandraTableManager(module, session).clearAllTables();
+    void clearTables() {
+        new CassandraTableManager(module, nonPrivilegedSession).clearAllTables();
     }
 }


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


[james-project] 12/29: JAMES-3061 Rename NO_MODULE to EMPTY_MODULE in CassandraModule

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 745a160a8b935aa4dd8aabe10dda6dc699268dd8
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Thu Feb 27 14:47:43 2020 +0700

    JAMES-3061 Rename NO_MODULE to EMPTY_MODULE in CassandraModule
---
 .../org/apache/james/backends/cassandra/components/CassandraModule.java | 2 +-
 .../org/apache/james/backends/cassandra/init/ClusterFactoryTest.java    | 2 +-
 .../james/backends/cassandra/init/ResilientClusterProviderTest.java     | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/components/CassandraModule.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/components/CassandraModule.java
index 9ea8665..e263ca1 100644
--- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/components/CassandraModule.java
+++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/components/CassandraModule.java
@@ -185,7 +185,7 @@ public interface CassandraModule {
             .build();
     }
 
-    CassandraModule NO_MODULE = builder().build();
+    CassandraModule EMPTY_MODULE = builder().build();
 
     List<CassandraTable> moduleTables();
 
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ClusterFactoryTest.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ClusterFactoryTest.java
index 75698f8..7799644 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ClusterFactoryTest.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ClusterFactoryTest.java
@@ -37,7 +37,7 @@ import com.datastax.driver.core.exceptions.NoHostAvailableException;
 class ClusterFactoryTest {
 
     @RegisterExtension
-    static CassandraClusterExtension cassandraExtension = new CassandraClusterExtension(CassandraModule.NO_MODULE);
+    static CassandraClusterExtension cassandraExtension = new CassandraClusterExtension(CassandraModule.EMPTY_MODULE);
 
     @AfterEach
     void tearDown(DockerCassandra dockerCassandra) {
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java
index f4493c6..5614391 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/init/ResilientClusterProviderTest.java
@@ -37,7 +37,7 @@ class ResilientClusterProviderTest {
     private static final String KEYSPACE = "my_keyspace";
 
     @RegisterExtension
-    static CassandraClusterExtension cassandraExtension = new CassandraClusterExtension(CassandraModule.NO_MODULE);
+    static CassandraClusterExtension cassandraExtension = new CassandraClusterExtension(CassandraModule.EMPTY_MODULE);
 
     @AfterEach
     void tearDown(DockerCassandra dockerCassandra) {


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


[james-project] 29/29: [Refactoring] removed unused fields

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 3f130661f8e03be3db5ee646f634aed7780810ba
Author: Rémi KOWALSKI <rk...@linagora.com>
AuthorDate: Fri Feb 28 17:23:47 2020 +0100

    [Refactoring] removed unused fields
---
 .../apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java b/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
index 4b57d53..1efa7cd 100644
--- a/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
+++ b/server/task/task-distributed/src/main/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueue.java
@@ -60,8 +60,6 @@ import reactor.rabbitmq.Sender;
 public class RabbitMQWorkQueue implements WorkQueue {
     private static final Logger LOGGER = LoggerFactory.getLogger(RabbitMQWorkQueue.class);
 
-    // Need at least one by receivers plus a shared one for senders
-    static final Integer MAX_CHANNELS_NUMBER = 5;
     static final String EXCHANGE_NAME = "taskManagerWorkQueueExchange";
     static final String QUEUE_NAME = "taskManagerWorkQueue";
     static final String ROUTING_KEY = "taskManagerWorkQueueRoutingKey";
@@ -74,7 +72,6 @@ public class RabbitMQWorkQueue implements WorkQueue {
     private final TaskManagerWorker worker;
     private final ReactorRabbitMQChannelPool channelPool;
     private final JsonTaskSerializer taskSerializer;
-    private Sender sender;
     private Receiver receiver;
     private UnicastProcessor<TaskId> sendCancelRequestsQueue;
     private Disposable sendCancelRequestsQueueHandle;


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


[james-project] 24/29: [Refactoring] extract immediate worker from RabbitMQWorkqueueTest

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 2bec84c8bd6a102d1af745291ae3756bbac15b05
Author: Rémi KOWALSKI <rk...@linagora.com>
AuthorDate: Fri Feb 28 15:40:32 2020 +0100

    [Refactoring] extract immediate worker from RabbitMQWorkqueueTest
---
 .../eventsourcing/distributed/ImmediateWorker.java | 60 ++++++++++++++++++++++
 .../distributed/RabbitMQWorkQueueTest.java         | 36 -------------
 2 files changed, 60 insertions(+), 36 deletions(-)

diff --git a/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/ImmediateWorker.java b/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/ImmediateWorker.java
new file mode 100644
index 0000000..93d8f75
--- /dev/null
+++ b/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/ImmediateWorker.java
@@ -0,0 +1,60 @@
+/****************************************************************
+ * 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.task.eventsourcing.distributed;
+
+import java.io.IOException;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.james.task.Task;
+import org.apache.james.task.TaskExecutionDetails;
+import org.apache.james.task.TaskId;
+import org.apache.james.task.TaskManagerWorker;
+import org.apache.james.task.TaskWithId;
+
+import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
+
+class ImmediateWorker implements TaskManagerWorker {
+
+    ConcurrentLinkedQueue<TaskWithId> tasks = new ConcurrentLinkedQueue<>();
+    ConcurrentLinkedQueue<Task.Result> results = new ConcurrentLinkedQueue<>();
+    ConcurrentLinkedQueue<TaskId> failedTasks = new ConcurrentLinkedQueue<>();
+
+    @Override
+    public Mono<Task.Result> executeTask(TaskWithId taskWithId) {
+        tasks.add(taskWithId);
+        return Mono.fromCallable(() -> taskWithId.getTask().run())
+            .doOnNext(result -> results.add(result))
+            .subscribeOn(Schedulers.elastic());
+    }
+
+    @Override
+    public void cancelTask(TaskId taskId) {
+    }
+
+    @Override
+    public void fail(TaskId taskId, Optional<TaskExecutionDetails.AdditionalInformation> additionalInformation, String errorMessage, Throwable reason) {
+        failedTasks.add(taskId);
+    }
+
+    @Override
+    public void close() throws IOException {
+    }
+}
diff --git a/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueueTest.java b/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueueTest.java
index ef6fd07..bf151e6 100644
--- a/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueueTest.java
+++ b/server/task/task-distributed/src/test/java/org/apache/james/task/eventsourcing/distributed/RabbitMQWorkQueueTest.java
@@ -27,10 +27,6 @@ import static org.awaitility.Duration.FIVE_HUNDRED_MILLISECONDS;
 import static org.awaitility.Duration.TWO_SECONDS;
 import static org.mockito.Mockito.spy;
 
-import java.io.IOException;
-import java.util.Optional;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.IntStream;
 
@@ -42,9 +38,7 @@ import org.apache.james.server.task.json.dto.TestTaskDTOModules;
 import org.apache.james.task.CompletedTask;
 import org.apache.james.task.MemoryReferenceTask;
 import org.apache.james.task.Task;
-import org.apache.james.task.TaskExecutionDetails;
 import org.apache.james.task.TaskId;
-import org.apache.james.task.TaskManagerWorker;
 import org.apache.james.task.TaskWithId;
 import org.awaitility.core.ConditionTimeoutException;
 import org.hamcrest.CoreMatchers;
@@ -53,9 +47,6 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-import reactor.core.publisher.Mono;
-import reactor.core.scheduler.Schedulers;
-
 class RabbitMQWorkQueueTest {
     private static final TaskId TASK_ID = TaskId.fromString("2c7f4081-aa30-11e9-bf6c-2d3b9e84aafd");
     private static final TaskId TASK_ID_2 = TaskId.fromString("3c7f4081-aa30-11e9-bf6c-2d3b9e84aafd");
@@ -73,33 +64,6 @@ class RabbitMQWorkQueueTest {
     private ImmediateWorker worker;
     private JsonTaskSerializer serializer;
 
-    private static class ImmediateWorker implements TaskManagerWorker {
-
-        ConcurrentLinkedQueue<TaskWithId> tasks = new ConcurrentLinkedQueue<>();
-        ConcurrentLinkedQueue<Task.Result> results = new ConcurrentLinkedQueue<>();
-        ConcurrentLinkedQueue<TaskId> failedTasks = new ConcurrentLinkedQueue<>();
-
-        @Override
-        public Mono<Task.Result> executeTask(TaskWithId taskWithId) {
-            tasks.add(taskWithId);
-            return Mono.fromCallable(() -> taskWithId.getTask().run())
-                .doOnNext(result -> results.add(result))
-                .subscribeOn(Schedulers.elastic());
-        }
-
-        @Override
-        public void cancelTask(TaskId taskId) {
-        }
-
-        @Override
-        public void fail(TaskId taskId, Optional<TaskExecutionDetails.AdditionalInformation> additionalInformation,String errorMessage, Throwable reason) {
-            failedTasks.add(taskId);
-        }
-
-        @Override
-        public void close() throws IOException {
-        }
-    }
 
     @BeforeEach
     void setUp() {


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


[james-project] 14/29: JAMES-3074 Extends UidValidity strong typing in the James code base

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 83cacbfd45b5711ff01be1a1fe606bf674b44083
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu Feb 20 17:53:16 2020 +0700

    JAMES-3074 Extends UidValidity strong typing in the James code base
---
 .../org/apache/james/mailbox/MessageManager.java   |   3 +-
 .../org/apache/james/mailbox/model/Mailbox.java    |   6 +-
 .../james/mailbox/model/MailboxAssertingTool.java  |   2 +-
 .../mailbox/model/MailboxAssertingToolTest.java    |   8 +-
 .../apache/james/mailbox/backup/zip/Zipper.java    |   2 +-
 .../mailbox/backup/MailboxMessageFixture.java      |   9 +-
 .../apache/james/mailbox/backup/ZipperTest.java    |   2 +-
 .../cassandra/mail/CassandraMailboxDAO.java        |   5 +-
 .../cassandra/mail/CassandraMailboxMapper.java     |   3 +-
 .../mail/CassandraIndexTableHandlerTest.java       |   3 +-
 .../mail/CassandraMailboxCounterDAOTest.java       |   3 +-
 .../cassandra/mail/CassandraMailboxDAOTest.java    |   5 +-
 .../CassandraMailboxMapperConcurrencyTest.java     |   3 +-
 .../cassandra/mail/CassandraMailboxMapperTest.java |   3 +-
 .../mail/CassandraModSeqProviderTest.java          |   3 +-
 .../cassandra/mail/CassandraUidProviderTest.java   |   3 +-
 .../mail/migration/MailboxPathV2MigrationTest.java |   3 +-
 .../SolveMailboxInconsistenciesServiceTest.java    |   5 +-
 ...asticSearchListeningMessageSearchIndexTest.java |   3 +-
 .../james/mailbox/jpa/mail/JPAMailboxMapper.java   |   3 +-
 .../james/mailbox/jpa/mail/model/JPAMailbox.java   |   7 +-
 .../jpa/mail/TransactionalMailboxMapper.java       |   3 +-
 .../LuceneMailboxMessageSearchIndexTest.java       |   7 +-
 .../james/mailbox/maildir/MaildirFolder.java       |  22 +-
 .../mailbox/maildir/mail/MaildirMailboxMapper.java |   3 +-
 .../inmemory/mail/InMemoryMailboxMapper.java       |   3 +-
 .../InMemoryCombinationManagerTestSystem.java      |   3 +-
 .../inmemory/InMemoryMessageManagerTestSystem.java |   3 +-
 .../spamassassin/SpamAssassinListenerTest.java     |   3 +-
 .../james/mailbox/store/MailboxMetaData.java       |   9 +-
 .../james/mailbox/store/StoreMailboxManager.java   |   5 +-
 .../james/mailbox/store/StoreMessageManager.java   |   3 +-
 .../james/mailbox/store/mail/MailboxMapper.java    |   3 +-
 .../james/mailbox/store/StoreRightManagerTest.java |   3 +-
 .../store/mail/model/ListMailboxAssertTest.java    |   3 +-
 .../store/mail/model/ListMessageAssertTest.java    |   3 +-
 .../store/mail/model/MailboxMapperACLTest.java     |   3 +-
 .../store/mail/model/MailboxMapperTest.java        |   3 +-
 .../store/mail/model/MessageIdMapperTest.java      |   3 +-
 .../store/mail/model/MessageMapperTest.java        |   3 +-
 .../mailbox/store/mail/model/MessageMoveTest.java  |   3 +-
 .../model/MessageWithAttachmentMapperTest.java     |   3 +-
 .../quota/DefaultUserQuotaRootResolverTest.java    |   5 +-
 .../mailbox/store/quota/QuotaCheckerTest.java      |   3 +-
 .../imap/api/message/response/StatusResponse.java  |  13 +-
 .../parser/AbstractSelectionCommandParser.java     |   7 +-
 .../imap/decode/parser/ExamineCommandParser.java   |   3 +-
 .../imap/decode/parser/SelectCommandParser.java    |   3 +-
 .../imap/encode/MailboxStatusResponseEncoder.java  |   7 +-
 .../request/AbstractMailboxSelectionRequest.java   |   7 +-
 .../james/imap/message/request/ExamineRequest.java |   3 +-
 .../james/imap/message/request/SelectRequest.java  |   3 +-
 .../message/response/MailboxStatusResponse.java    |   7 +-
 .../processor/AbstractMessageRangeProcessor.java   |   3 +-
 .../imap/processor/AbstractSelectionProcessor.java |   7 +-
 .../james/imap/processor/AppendProcessor.java      |   3 +-
 .../james/imap/processor/ExamineProcessor.java     |   5 +-
 .../james/imap/processor/SelectProcessor.java      |   5 +-
 .../james/imap/processor/StatusProcessor.java      |   5 +-
 .../encode/MailboxStatusResponseEncoderTest.java   |   3 +-
 .../james/imap/processor/CopyProcessorTest.java    |   5 +-
 .../james/imap/processor/MoveProcessorTest.java    |   5 +-
 .../processor/base/MailboxEventAnalyserTest.java   |   3 +-
 .../adapter/mailbox/MailboxManagementTest.java     |   3 +-
 .../james/pop3server/mailbox/MailboxAdapter.java   | 349 +++++++++++----------
 65 files changed, 350 insertions(+), 285 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/MessageManager.java b/mailbox/api/src/main/java/org/apache/james/mailbox/MessageManager.java
index e91c432..52c0f6e 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/MessageManager.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/MessageManager.java
@@ -48,6 +48,7 @@ import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageResult;
 import org.apache.james.mailbox.model.MessageResultIterator;
 import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mime4j.dom.Message;
 import org.apache.james.mime4j.message.DefaultMessageWriter;
 
@@ -377,7 +378,7 @@ public interface MessageManager {
          * 
          * @return UIDVALIDITY
          */
-        long getUidValidity();
+        UidValidity getUidValidity();
 
         /**
          * Gets the next UID predicted. The returned UID is not guaranteed to be
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/Mailbox.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/Mailbox.java
index 04868eb..2f1a613 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/Mailbox.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/Mailbox.java
@@ -33,10 +33,10 @@ public class Mailbox {
     private String namespace;
     private Username user;
     private String name;
-    private final long uidValidity;
+    private final UidValidity uidValidity;
     private MailboxACL acl = MailboxACL.EMPTY;
 
-    public Mailbox(MailboxPath path, long uidValidity, MailboxId mailboxId) {
+    public Mailbox(MailboxPath path, UidValidity uidValidity, MailboxId mailboxId) {
         this.id = mailboxId;
         this.namespace = path.getNamespace();
         this.user = path.getUser();
@@ -113,7 +113,7 @@ public class Mailbox {
      * Gets the current UID VALIDITY for this mailbox.
      * @return uid validity
      */
-    public long getUidValidity() {
+    public UidValidity getUidValidity() {
         return uidValidity;
     }
 
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingTool.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingTool.java
index 1292651..9d31b5b 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingTool.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingTool.java
@@ -51,7 +51,7 @@ public class MailboxAssertingTool {
             if (!Objects.equals(actual.getACL(), expected.getACL())) {
                 failWithMessage(aclFailMessage(expected, actual));
             }
-            if (actual.getUidValidity() != expected.getUidValidity()) {
+            if (!Objects.equals(actual.getUidValidity(), expected.getUidValidity())) {
                 failWithMessage(uidValidityFailMessage(expected, actual));
             }
             return this;
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingToolTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingToolTest.java
index 573bc36..8e3377f 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingToolTest.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxAssertingToolTest.java
@@ -31,7 +31,7 @@ class MailboxAssertingToolTest {
     private static final Username USER = Username.of("user");
     private static final Username USER1 = Username.of("user1");
 
-    private static final long UID_VALIDITY = 42;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
     private static final TestId MAILBOX_ID = TestId.of(24);
 
     @Nested
@@ -83,7 +83,7 @@ class MailboxAssertingToolTest {
         @Test
         void isEqualToShouldFailWithNotEqualUidValidity() {
             Mailbox mailbox1 = new Mailbox(MailboxPath.forUser(USER, "name"), UID_VALIDITY, MAILBOX_ID);
-            Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(USER, "name"), UID_VALIDITY + 1, MAILBOX_ID);
+            Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(USER, "name"), UidValidity.of(UID_VALIDITY.asLong() + 1), MAILBOX_ID);
 
             assertThatThrownBy(() -> MailboxAssertingTool.assertThat(mailbox1).isEqualTo(mailbox2))
                 .isInstanceOf(AssertionError.class);
@@ -157,7 +157,7 @@ class MailboxAssertingToolTest {
         @Test
         void isEqualToShouldFailWithNotEqualUidValidity() {
             Mailbox mailbox1 = new Mailbox(MailboxPath.forUser(USER, "name"), UID_VALIDITY, MAILBOX_ID);
-            Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(USER, "name"), UID_VALIDITY + 1, MAILBOX_ID);
+            Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(USER, "name"), UidValidity.of(UID_VALIDITY.asLong() + 1), MAILBOX_ID);
 
             assertThatThrownBy(() -> {
                     SoftAssertions.assertSoftly(softly -> {
@@ -167,7 +167,7 @@ class MailboxAssertingToolTest {
                     });
                 })
                 .isInstanceOf(AssertionError.class)
-                .hasMessageContaining("Expected UID Validity to be <43> but was <42>");
+                .hasMessageContaining("Expected UID Validity to be <UidValidity{uidValidity=43}> but was <UidValidity{uidValidity=42}");
         }
 
         @Test
diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/Zipper.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/Zipper.java
index 0600b4b..4077c1e 100644
--- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/Zipper.java
+++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/zip/Zipper.java
@@ -92,7 +92,7 @@ public class Zipper implements ArchiveService {
 
         archiveEntry.addExtraField(EntryTypeExtraField.TYPE_MAILBOX);
         archiveEntry.addExtraField(new MailboxIdExtraField(mailbox.getMailboxId().serialize()));
-        archiveEntry.addExtraField(new UidValidityExtraField(mailbox.getUidValidity()));
+        archiveEntry.addExtraField(new UidValidityExtraField(mailbox.getUidValidity().asLong()));
 
         archiveOutputStream.putArchiveEntry(archiveEntry);
         archiveOutputStream.closeArchiveEntry();
diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
index ec97990..50f8a76 100644
--- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
+++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java
@@ -40,6 +40,7 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
 
@@ -100,10 +101,10 @@ public interface MailboxMessageFixture {
     MailboxPath MAILBOX_PATH_USER1_MAILBOX2 = MailboxPath.forUser(USER, MAILBOX_2_NAME);
     MailboxPath MAILBOX_PATH_OTHER_USER_MAILBOX1 = MailboxPath.forUser(OTHER_USER, MAILBOX_OTHER_USER_NAME);
 
-    Mailbox MAILBOX_1 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX1, 42, MAILBOX_ID_1);
-    Mailbox MAILBOX_1_OTHER_USER = new Mailbox(MAILBOX_PATH_OTHER_USER_MAILBOX1, 42, MAILBOX_ID_11);
-    Mailbox MAILBOX_1_SUB_1 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX1_SUB_1, 420, TestId.of(11L));
-    Mailbox MAILBOX_2 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX2, 43, MAILBOX_ID_2);
+    Mailbox MAILBOX_1 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX1, UidValidity.of(42), MAILBOX_ID_1);
+    Mailbox MAILBOX_1_OTHER_USER = new Mailbox(MAILBOX_PATH_OTHER_USER_MAILBOX1, UidValidity.of(42), MAILBOX_ID_11);
+    Mailbox MAILBOX_1_SUB_1 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX1_SUB_1, UidValidity.of(420), TestId.of(11L));
+    Mailbox MAILBOX_2 = new Mailbox(MAILBOX_PATH_USER1_MAILBOX2, UidValidity.of(43), MAILBOX_ID_2);
 
     List<MailboxAnnotation> NO_ANNOTATION = ImmutableList.of();
 
diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java
index 7200cc7..e489157 100644
--- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java
+++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java
@@ -195,7 +195,7 @@ class ZipperTest {
                     hasName(MAILBOX_1.getName() + "/")
                         .containsExtraFields(
                             new MailboxIdExtraField(MAILBOX_1.getMailboxId()),
-                            new UidValidityExtraField(MAILBOX_1.getUidValidity())));
+                            new UidValidityExtraField(MAILBOX_1.getUidValidity().asLong())));
         }
     }
 
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAO.java
index 3c7a9f9..e5c097c 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAO.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAO.java
@@ -43,6 +43,7 @@ import org.apache.james.mailbox.cassandra.mail.utils.MailboxBaseTupleUtil;
 import org.apache.james.mailbox.cassandra.table.CassandraMailboxTable;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 
 import com.datastax.driver.core.PreparedStatement;
 import com.datastax.driver.core.Row;
@@ -116,7 +117,7 @@ public class CassandraMailboxDAO {
         return executor.executeVoid(insertStatement.bind()
             .setUUID(ID, cassandraId.asUuid())
             .setString(NAME, mailbox.getName())
-            .setLong(UIDVALIDITY, mailbox.getUidValidity())
+            .setLong(UIDVALIDITY, mailbox.getUidValidity().asLong())
             .setUDTValue(MAILBOX_BASE, mailboxBaseTupleUtil.createMailboxBaseUDT(mailbox.getNamespace(), mailbox.getUser())));
     }
 
@@ -144,7 +145,7 @@ public class CassandraMailboxDAO {
                 row.getUDTValue(MAILBOX_BASE).getString(CassandraMailboxTable.MailboxBase.NAMESPACE),
                 Username.of(row.getUDTValue(MAILBOX_BASE).getString(CassandraMailboxTable.MailboxBase.USER)),
                 row.getString(NAME)),
-            row.getLong(UIDVALIDITY),
+            UidValidity.of(row.getLong(UIDVALIDITY)),
             cassandraId);
     }
 
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 bfeb59f..daf71ce 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
@@ -36,6 +36,7 @@ import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.apache.james.util.ReactorUtils;
@@ -154,7 +155,7 @@ public class CassandraMailboxMapper implements MailboxMapper {
     }
 
     @Override
-    public Mailbox create(MailboxPath mailboxPath, long uidValidity) throws MailboxException {
+    public Mailbox create(MailboxPath mailboxPath, UidValidity uidValidity) throws MailboxException {
         CassandraId cassandraId = CassandraId.timeBased();
         Mailbox mailbox = new Mailbox(mailboxPath, uidValidity, cassandraId);
 
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
index dc739f4..d100737 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraIndexTableHandlerTest.java
@@ -44,6 +44,7 @@ import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.junit.jupiter.api.BeforeEach;
@@ -55,7 +56,7 @@ class CassandraIndexTableHandlerTest {
     private static final CassandraId MAILBOX_ID = CassandraId.timeBased();
     private static final MessageUid MESSAGE_UID = MessageUid.of(18L);
     private static final CassandraMessageId CASSANDRA_MESSAGE_ID = new CassandraMessageId.Factory().generate();
-    private static final int UID_VALIDITY = 15;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(15);
     private static final ModSeq MODSEQ = ModSeq.of(17);
 
     @RegisterExtension
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 67e2007..b87fdd3 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
@@ -29,12 +29,13 @@ import org.apache.james.mailbox.cassandra.modules.CassandraMailboxCounterModule;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxCounters;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraMailboxCounterDAOTest {
-    private static final int UID_VALIDITY = 15;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(15);
     private static final CassandraId MAILBOX_ID = CassandraId.timeBased();
 
     @RegisterExtension
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAOTest.java
index 459bd6e..f13a96f 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAOTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxDAOTest.java
@@ -35,13 +35,14 @@ import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraMailboxDAOTest {
-    private static final int UID_VALIDITY_1 = 145;
-    private static final int UID_VALIDITY_2 = 147;
+    private static final UidValidity UID_VALIDITY_1 = UidValidity.of(145);
+    private static final UidValidity UID_VALIDITY_2 = UidValidity.of(147);
     private static final Username USER = Username.of("user");
     private static final MailboxPath NEW_MAILBOX_PATH = MailboxPath.forUser(USER, "xyz");
     private static CassandraId CASSANDRA_ID_1 = CassandraId.timeBased();
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java
index 99044c8..54e7290 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperConcurrencyTest.java
@@ -34,6 +34,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -41,7 +42,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraMailboxMapperConcurrencyTest {
 
-    private static final int UID_VALIDITY = 52;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(52);
     private static final MailboxPath MAILBOX_PATH = MailboxPath.forUser(Username.of("user"), "name");
     private static final int THREAD_COUNT = 10;
     private static final int OPERATION_COUNT = 10;
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 a8af418..c724053 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
@@ -44,6 +44,7 @@ import org.apache.james.mailbox.exception.TooLongMailboxNameException;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.search.ExactName;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.model.search.Wildcard;
@@ -58,7 +59,7 @@ import com.github.fge.lambdas.Throwing;
 import com.github.fge.lambdas.runnable.ThrowingRunnable;
 
 class CassandraMailboxMapperTest {
-    private static final int UID_VALIDITY = 52;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(52);
     private static final Username USER = Username.of("user");
     private static final CassandraId MAILBOX_ID = CassandraId.timeBased();
     private static final MailboxPath MAILBOX_PATH = MailboxPath.forUser(USER, "name");
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProviderTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProviderTest.java
index 93637ef..6c328a4 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProviderTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraModSeqProviderTest.java
@@ -34,6 +34,7 @@ import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.modules.CassandraModSeqModule;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -55,7 +56,7 @@ class CassandraModSeqProviderTest {
     void setUp(CassandraCluster cassandra) {
         modSeqProvider = new CassandraModSeqProvider(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION);
         MailboxPath path = new MailboxPath("gsoc", Username.of("ieugen"), "Trash");
-        mailbox = new Mailbox(path, 1234, CASSANDRA_ID);
+        mailbox = new Mailbox(path, UidValidity.of(1234), CASSANDRA_ID);
     }
 
     @Test
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProviderTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProviderTest.java
index 88c4294..80c43b0 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProviderTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraUidProviderTest.java
@@ -35,6 +35,7 @@ import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.modules.CassandraUidModule;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -55,7 +56,7 @@ class CassandraUidProviderTest {
     void setUp(CassandraCluster cassandra) {
         uidProvider = new CassandraUidProvider(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION);
         MailboxPath path = new MailboxPath("gsoc", Username.of("ieugen"), "Trash");
-        mailbox = new Mailbox(path, 1234, CASSANDRA_ID);
+        mailbox = new Mailbox(path, UidValidity.of(1234), CASSANDRA_ID);
     }
 
     @Test
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 2657eb7..82ee289 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
@@ -41,6 +41,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.assertj.core.api.SoftAssertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -49,7 +50,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 class MailboxPathV2MigrationTest {
 
     private static final MailboxPath MAILBOX_PATH_1 = MailboxPath.forUser(Username.of("bob"), "Important");
-    private static final int UID_VALIDITY_1 = 452;
+    private static final UidValidity UID_VALIDITY_1 = UidValidity.of(452);
     private static final CassandraId MAILBOX_ID_1 = CassandraId.timeBased();
 
     public static final CassandraModule MODULES = CassandraModule.aggregateModules(
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMailboxInconsistenciesServiceTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMailboxInconsistenciesServiceTest.java
index 167fcb8..6db7ae0 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMailboxInconsistenciesServiceTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMailboxInconsistenciesServiceTest.java
@@ -40,6 +40,7 @@ import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.task.Task.Result;
 import org.assertj.core.api.SoftAssertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -49,8 +50,8 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 import nl.jqno.equalsverifier.EqualsVerifier;
 
 class SolveMailboxInconsistenciesServiceTest {
-    private static final int UID_VALIDITY_1 = 145;
-    private static final int UID_VALIDITY_2 = 147;
+    private static final UidValidity UID_VALIDITY_1 = UidValidity.ofValid(145);
+    private static final UidValidity UID_VALIDITY_2 = UidValidity.ofValid(147);
     private static final Username USER = Username.of("user");
     private static final MailboxPath MAILBOX_PATH = MailboxPath.forUser(USER, "abc");
     private static final MailboxPath NEW_MAILBOX_PATH = MailboxPath.forUser(USER, "xyz");
diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
index b126711..5a94b95 100644
--- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
+++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
@@ -62,6 +62,7 @@ import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.SearchQuery;
 import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.store.Authorizator;
 import org.apache.james.mailbox.store.FakeAuthenticator;
@@ -177,7 +178,7 @@ class ElasticSearchListeningMessageSearchIndexTest {
             messageToElasticSearchJson, sessionProvider, new MailboxIdRoutingKeyFactory());
         session = sessionProvider.createSystemSession(USERNAME);
 
-        mailbox = mapperFactory.getMailboxMapper(session).create(MailboxPath.forUser(USERNAME, DefaultMailboxes.INBOX), MAILBOX_ID.id);
+        mailbox = mapperFactory.getMailboxMapper(session).create(MailboxPath.forUser(USERNAME, DefaultMailboxes.INBOX), UidValidity.of(MAILBOX_ID.id));
     }
 
     @Test
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMailboxMapper.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMailboxMapper.java
index 40613e9..966101a 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMailboxMapper.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMailboxMapper.java
@@ -41,6 +41,7 @@ import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.store.MailboxExpressionBackwardCompatibility;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
@@ -84,7 +85,7 @@ public class JPAMailboxMapper extends JPATransactionalMapper implements MailboxM
     }
     
     @Override
-    public Mailbox create(MailboxPath mailboxPath, long uidValidity) throws MailboxException {
+    public Mailbox create(MailboxPath mailboxPath, UidValidity uidValidity) throws MailboxException {
         try {
             if (isPathAlreadyUsedByAnotherMailbox(mailboxPath)) {
                 throw new MailboxExistsException(mailboxPath.getName());
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/JPAMailbox.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/JPAMailbox.java
index 0e533e8..730ce90 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/JPAMailbox.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/JPAMailbox.java
@@ -33,6 +33,7 @@ import org.apache.james.core.Username;
 import org.apache.james.mailbox.jpa.JPAId;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 
 @Entity(name = "Mailbox")
 @Table(name = "JAMES_MAILBOX")
@@ -105,11 +106,11 @@ public class JPAMailbox {
     public JPAMailbox() {
     }
     
-    public JPAMailbox(MailboxPath path, long uidValidity) {
+    public JPAMailbox(MailboxPath path, UidValidity uidValidity) {
         this.name = path.getName();
         this.user = path.getUser().asString();
         this.namespace = path.getNamespace();
-        this.uidValidity = uidValidity;
+        this.uidValidity = uidValidity.asLong();
     }
 
     public JPAMailbox(Mailbox mailbox) {
@@ -130,7 +131,7 @@ public class JPAMailbox {
 
     public Mailbox toMailbox() {
         MailboxPath path = new MailboxPath(namespace, Username.of(user), name);
-        return new Mailbox(path, uidValidity, new JPAId(mailboxId));
+        return new Mailbox(path, UidValidity.of(uidValidity), new JPAId(mailboxId));
     }
 
     public void setMailboxId(long mailboxId) {
diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalMailboxMapper.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalMailboxMapper.java
index cce5fdc..a40e189 100644
--- a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalMailboxMapper.java
+++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalMailboxMapper.java
@@ -31,6 +31,7 @@ import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.apache.james.mailbox.store.transaction.Mapper;
@@ -53,7 +54,7 @@ public class TransactionalMailboxMapper implements MailboxMapper {
     }
 
     @Override
-    public Mailbox create(MailboxPath mailboxPath, long uidValidity) throws MailboxException {
+    public Mailbox create(MailboxPath mailboxPath, UidValidity uidValidity) throws MailboxException {
         return wrapped.execute(() -> wrapped.create(mailboxPath, uidValidity));
     }
 
diff --git a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java
index 24fcd4c..6ff52fb 100644
--- a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java
+++ b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMailboxMessageSearchIndexTest.java
@@ -47,6 +47,7 @@ import org.apache.james.mailbox.model.SearchQuery.Sort.Order;
 import org.apache.james.mailbox.model.SearchQuery.Sort.SortClause;
 import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.MessageBuilder;
 import org.apache.lucene.store.RAMDirectory;
 import org.junit.jupiter.api.BeforeEach;
@@ -61,9 +62,9 @@ class LuceneMailboxMessageSearchIndexTest {
     static final TestId TEST_ID_3 = TestId.of(2);
 
     static final Username BOB = Username.of("bob");
-    Mailbox mailbox = new Mailbox(MailboxPath.forUser(BOB, "box"), 18, TEST_ID_1);
-    Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(BOB, "box"), 19, TEST_ID_2);
-    Mailbox mailbox3 = new Mailbox(MailboxPath.forUser(BOB, "box"), 12, TEST_ID_3);
+    Mailbox mailbox = new Mailbox(MailboxPath.forUser(BOB, "box"), UidValidity.of(18), TEST_ID_1);
+    Mailbox mailbox2 = new Mailbox(MailboxPath.forUser(BOB, "box"), UidValidity.of(19), TEST_ID_2);
+    Mailbox mailbox3 = new Mailbox(MailboxPath.forUser(BOB, "box"), UidValidity.of(12), TEST_ID_3);
     LuceneMessageSearchIndex index;
     MailboxSession session;
 
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
index e716238..2f4418e 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
@@ -53,11 +53,13 @@ import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.EntryKey;
 import org.apache.james.mailbox.model.MailboxACL.Rfc4314Rights;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class MaildirFolder {
     private static final Logger LOGGER = LoggerFactory.getLogger(MaildirFolder.class);
+    private static final UidValidity DEFAULT_UID_VALIDITY = UidValidity.of(-1);
 
     public static final String VALIDITY_FILE = "james-uidvalidity";
     public static final String UIDLIST_FILE = "james-uidlist";
@@ -77,7 +79,7 @@ public class MaildirFolder {
 
     private Optional<MessageUid> lastUid;
     private int messageCount = 0;
-    private long uidValidity = -1;
+    private UidValidity uidValidity = DEFAULT_UID_VALIDITY;
     private MailboxACL acl;
     private boolean messageNameStrictParse = false;
 
@@ -249,8 +251,8 @@ public class MaildirFolder {
      * Returns the uidValidity of this mailbox
      * @return The uidValidity
      */
-    public long getUidValidity() throws IOException {
-        if (uidValidity == -1) {
+    public UidValidity getUidValidity() throws IOException {
+        if (uidValidity.equals(DEFAULT_UID_VALIDITY)) {
             uidValidity = readUidValidity();
         }
         return uidValidity;
@@ -259,7 +261,7 @@ public class MaildirFolder {
     /**
      * Sets the uidValidity for this mailbox and writes it to the file system
      */
-    public void setUidValidity(long uidValidity) throws IOException {
+    public void setUidValidity(UidValidity uidValidity) throws IOException {
         saveUidValidity(uidValidity);
         this.uidValidity = uidValidity;
     }
@@ -271,7 +273,7 @@ public class MaildirFolder {
      * @return The uidValidity
      * @throws IOException if there are problems with the validity file
      */
-    private long readUidValidity() throws IOException {
+    private UidValidity readUidValidity() throws IOException {
         File validityFile = new File(rootFolder, VALIDITY_FILE);
         if (!validityFile.exists()) {
             return resetUidValidity();
@@ -280,20 +282,20 @@ public class MaildirFolder {
              InputStreamReader isr = new InputStreamReader(fis)) {
             char[] uidValidity = new char[20];
             int len = isr.read(uidValidity);
-            return Long.parseLong(String.valueOf(uidValidity, 0, len).trim());
+            return UidValidity.of(Long.parseLong(String.valueOf(uidValidity, 0, len).trim()));
         }
     }
 
     /**
      * Save the given uidValidity to the file system
      */
-    private void saveUidValidity(long uidValidity) throws IOException {
+    private void saveUidValidity(UidValidity uidValidity) throws IOException {
         File validityFile = new File(rootFolder, VALIDITY_FILE);
         if (!validityFile.createNewFile()) {
             throw new IOException("Could not create file " + validityFile);
         }
         try (FileOutputStream fos = new FileOutputStream(validityFile)) {
-            fos.write(String.valueOf(uidValidity).getBytes());
+            fos.write(String.valueOf(uidValidity.asLong()).getBytes());
         }
     }
 
@@ -339,9 +341,9 @@ public class MaildirFolder {
      * Sets and returns a new uidValidity for this folder.
      * @return the new uidValidity
      */
-    private long resetUidValidity() throws IOException {
+    private UidValidity resetUidValidity() throws IOException {
         // using the timestamp as uidValidity
-        long timestamp = System.currentTimeMillis();
+        UidValidity timestamp = UidValidity.of(System.currentTimeMillis());
         setUidValidity(timestamp);
         return timestamp;
     }
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java
index 4be42b9..f6e8195 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java
@@ -42,6 +42,7 @@ import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.model.search.PrefixedWildcard;
 import org.apache.james.mailbox.store.MailboxExpressionBackwardCompatibility;
@@ -158,7 +159,7 @@ public class MaildirMailboxMapper extends NonTransactionalMapper implements Mail
     }
 
     @Override
-    public Mailbox create(MailboxPath mailboxPath, long uidValidity) throws MailboxException {
+    public Mailbox create(MailboxPath mailboxPath, UidValidity uidValidity) throws MailboxException {
         MaildirId maildirId = MaildirId.random();
         Mailbox mailbox = new Mailbox(mailboxPath, uidValidity, maildirId);
         MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
diff --git a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java
index 9dc6491..c990f48 100644
--- a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java
+++ b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java
@@ -36,6 +36,7 @@ import org.apache.james.mailbox.model.MailboxACL.NameType;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 
@@ -93,7 +94,7 @@ public class InMemoryMailboxMapper implements MailboxMapper {
     }
 
     @Override
-    public Mailbox create(MailboxPath mailboxPath, long uidValidity) throws MailboxException {
+    public Mailbox create(MailboxPath mailboxPath, UidValidity uidValidity) throws MailboxException {
         InMemoryId id = InMemoryId.of(mailboxIdGenerator.incrementAndGet());
         Mailbox mailbox = new Mailbox(mailboxPath, uidValidity, id);
 
diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryCombinationManagerTestSystem.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryCombinationManagerTestSystem.java
index 9001e4d..3087bef 100644
--- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryCombinationManagerTestSystem.java
+++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryCombinationManagerTestSystem.java
@@ -25,10 +25,11 @@ import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.CombinationManagerTestSystem;
 
 public class InMemoryCombinationManagerTestSystem extends CombinationManagerTestSystem {
-    private static final int UID_VALIDITY = 1024;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(1024);
 
     private final InMemoryMailboxManager inMemoryMailboxManager;
 
diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageManagerTestSystem.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageManagerTestSystem.java
index a6cbe0d..4933ee5 100644
--- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageManagerTestSystem.java
+++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageManagerTestSystem.java
@@ -24,11 +24,12 @@ import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.MessageManagerTestSystem;
 
 public class InMemoryMessageManagerTestSystem extends MessageManagerTestSystem {
 
-    private static final int UID_VALIDITY = 1024;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(1024);
 
     private final MailboxManager mailboxManager;
 
diff --git a/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java b/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
index 63bab78..4227d3b 100644
--- a/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
+++ b/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
@@ -47,6 +47,7 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageMoves;
 import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
 import org.apache.james.mailbox.store.StoreMailboxManager;
 import org.apache.james.mailbox.store.SystemMailboxesProviderImpl;
@@ -60,7 +61,7 @@ import org.junit.jupiter.api.Test;
 class SpamAssassinListenerTest {
     static final Username USER = Username.of("user");
     static final MailboxSession MAILBOX_SESSION = MailboxSessionUtil.create(USER);
-    static final int UID_VALIDITY = 43;
+    static final UidValidity UID_VALIDITY = UidValidity.of(43);
     static final TestMessageId MESSAGE_ID = TestMessageId.of(45);
 
     SpamAssassin spamAssassin;
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxMetaData.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxMetaData.java
index 479f598..36410c6 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxMetaData.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxMetaData.java
@@ -30,6 +30,7 @@ import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.ModSeq;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxACL;
+import org.apache.james.mailbox.model.UidValidity;
 
 import com.google.common.collect.ImmutableList;
 
@@ -38,7 +39,7 @@ import com.google.common.collect.ImmutableList;
  */
 public class MailboxMetaData implements MessageManager.MetaData {
 
-    public static MailboxMetaData sensibleInformationFree(MailboxACL resolvedAcl, long uidValidity, boolean writeable, boolean modSeqPermanent) throws MailboxException {
+    public static MailboxMetaData sensibleInformationFree(MailboxACL resolvedAcl, UidValidity uidValidity, boolean writeable, boolean modSeqPermanent) throws MailboxException {
         ImmutableList<MessageUid> recents = ImmutableList.of();
         MessageUid uidNext = MessageUid.MIN_VALUE;
         ModSeq highestModSeq = ModSeq.first();
@@ -62,7 +63,7 @@ public class MailboxMetaData implements MessageManager.MetaData {
     private final long recentCount;
     private final List<MessageUid> recent;
     private final Flags permanentFlags;
-    private final long uidValidity;
+    private final UidValidity uidValidity;
     private final MessageUid nextUid;
     private final long messageCount;
     private final long unseenCount;
@@ -72,7 +73,7 @@ public class MailboxMetaData implements MessageManager.MetaData {
     private final boolean modSeqPermanent;
     private final MailboxACL acl;
 
-    public MailboxMetaData(List<MessageUid> recent, Flags permanentFlags, long uidValidity, MessageUid uidNext, ModSeq highestModSeq, long messageCount, long unseenCount, MessageUid firstUnseen, boolean writeable, boolean modSeqPermanent, MailboxACL acl) {
+    public MailboxMetaData(List<MessageUid> recent, Flags permanentFlags, UidValidity uidValidity, MessageUid uidNext, ModSeq highestModSeq, long messageCount, long unseenCount, MessageUid firstUnseen, boolean writeable, boolean modSeqPermanent, MailboxACL acl) {
         this.recent = Optional.ofNullable(recent).orElseGet(ArrayList::new);
         this.highestModSeq = highestModSeq;
         this.recentCount = this.recent.size();
@@ -104,7 +105,7 @@ public class MailboxMetaData implements MessageManager.MetaData {
     }
 
     @Override
-    public long getUidValidity() {
+    public UidValidity getUidValidity() {
         return uidValidity;
     }
 
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 77eae6b..6e61512 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
@@ -70,6 +70,7 @@ import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MultimailboxesSearchQuery;
 import org.apache.james.mailbox.model.QuotaRoot;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.model.search.PrefixedWildcard;
 import org.apache.james.mailbox.quota.QuotaManager;
@@ -217,8 +218,8 @@ public class StoreMailboxManager implements MailboxManager {
     /**
      * Generate and return the next uid validity
      */
-    protected int randomUidValidity() {
-        return Math.abs(RANDOM.nextInt());
+    protected UidValidity randomUidValidity() {
+        return UidValidity.of(Math.abs(RANDOM.nextInt()));
     }
 
     @Override
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 259cd7b..2736d37 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
@@ -73,6 +73,7 @@ import org.apache.james.mailbox.model.MessageMoves;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageResultIterator;
 import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
@@ -534,7 +535,7 @@ public class StoreMessageManager implements MessageManager {
         }
         List<MessageUid> recent;
         Flags permanentFlags = getPermanentFlags(mailboxSession);
-        long uidValidity = getMailboxEntity().getUidValidity();
+        UidValidity uidValidity = getMailboxEntity().getUidValidity();
         MessageUid uidNext = mapperFactory.getMessageMapper(mailboxSession).getLastUid(mailbox)
                 .map(MessageUid::next)
                 .orElse(MessageUid.MIN_VALUE);
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
index 35885b5..9973d8f 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
@@ -29,6 +29,7 @@ import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.store.transaction.Mapper;
 
@@ -42,7 +43,7 @@ public interface MailboxMapper extends Mapper {
     /**
      * Create a {@link Mailbox} with the given {@link MailboxPath} and uid to the underlying storage
      */
-    Mailbox create(MailboxPath mailboxPath, long uidValidity) throws MailboxException;
+    Mailbox create(MailboxPath mailboxPath, UidValidity uidValidity) throws MailboxException;
 
     /**
      * Rename the given {@link Mailbox} to the underlying storage
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreRightManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreRightManagerTest.java
index a9e7933..7aa4a76 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreRightManagerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreRightManagerTest.java
@@ -51,6 +51,7 @@ import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.TestId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -58,7 +59,7 @@ import org.junit.jupiter.api.Test;
 class StoreRightManagerTest {
 
     static final MailboxId MAILBOX_ID = TestId.of(42);
-    static final long UID_VALIDITY = 3421L;
+    static final UidValidity UID_VALIDITY = UidValidity.of(3421L);
 
     StoreRightManager storeRightManager;
     MailboxSession aliceSession;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMailboxAssertTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMailboxAssertTest.java
index de14605..0d158a6 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMailboxAssertTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMailboxAssertTest.java
@@ -29,6 +29,7 @@ import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.TestId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
@@ -39,7 +40,7 @@ class ListMailboxAssertTest {
     static final String NAME = "name";
     static final Username USER = Username.of("user");
     static final String NAMESPACE = "namespace";
-    static final long UID_VALIDITY = 42;
+    static final UidValidity UID_VALIDITY = UidValidity.of(42);
     static final MailboxId MAILBOX_ID_1 = TestId.of(1);
     static final MailboxId MAILBOX_ID_2 = TestId.of(2);
     static final Mailbox MAILBOX_1 = new Mailbox(new MailboxPath(NAMESPACE, USER, NAME), UID_VALIDITY, MAILBOX_ID_1);
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java
index bd50a2a..99318de 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/ListMessageAssertTest.java
@@ -38,6 +38,7 @@ import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.TestId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
 import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
 import org.junit.jupiter.api.BeforeEach;
@@ -49,7 +50,7 @@ class ListMessageAssertTest {
     static final String BODY_CONTENT2 = "Subject: Test2 \n\nBody2\n.\n";
     static final String BODY_CONTENT1 = "Subject: Test1 \n\nBody1\n.\n";
     static final int BODY_START = 16;
-    static final int UID_VALIDITY = 42;
+    static final UidValidity UID_VALIDITY = UidValidity.of(42);
     static final MailboxId MAILBOX_ID = TestId.of(1);
     static final MessageUid MESSAGE_UID = MessageUid.of(2);
     static final MessageId MESSAGE_ID = new DefaultMessageId();
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperACLTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperACLTest.java
index 408e6ad..744892f 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperACLTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperACLTest.java
@@ -30,6 +30,7 @@ import org.apache.james.mailbox.model.MailboxACL.EntryKey;
 import org.apache.james.mailbox.model.MailboxACL.Rfc4314Rights;
 import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -37,7 +38,7 @@ import org.junit.jupiter.api.Test;
 import com.google.common.collect.ImmutableMap;
 
 public abstract class MailboxMapperACLTest {
-    private static final long UID_VALIDITY = 42;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
     private static final boolean POSITIVE = true;
     private static final boolean NEGATIVE = !POSITIVE;
     private static final Username USER = Username.of("user");
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java
index 89ffb3b..aee7ac5 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MailboxMapperTest.java
@@ -33,6 +33,7 @@ import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.search.ExactName;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.model.search.PrefixedWildcard;
@@ -48,7 +49,7 @@ import org.junit.jupiter.api.Test;
 public abstract class MailboxMapperTest {
 
     private static final char DELIMITER = '.';
-    private static final long UID_VALIDITY = 42;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
     private static final Username BENWA = Username.of("benwa");
     private static final MailboxPath benwaInboxPath = MailboxPath.forUser(BENWA, "INBOX");
     private static final MailboxPath benwaWorkPath = MailboxPath.forUser(BENWA, "INBOX" + DELIMITER + "work");
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
index 630afc7..731f35a 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
@@ -42,6 +42,7 @@ import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.apache.james.mailbox.store.mail.MessageIdMapper;
@@ -64,7 +65,7 @@ public abstract class MessageIdMapperTest {
 
     private static final char DELIMITER = '.';
     private static final int BODY_START = 16;
-    protected static final long UID_VALIDITY = 42;
+    protected static final UidValidity UID_VALIDITY = UidValidity.of(42);
 
     private MessageMapper messageMapper;
     private MailboxMapper mailboxMapper;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
index 1e4b4e5..b199021 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
@@ -48,6 +48,7 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.store.FlagsUpdateCalculator;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
@@ -69,7 +70,7 @@ public abstract class MessageMapperTest {
     private static final char DELIMITER = '.';
     private static final int LIMIT = 10;
     private static final int BODY_START = 16;
-    private static final int UID_VALIDITY = 42;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
     private static final String USER_FLAG = "userFlag";
 
     private static final String CUSTOMS_USER_FLAGS_VALUE = "CustomsFlags";
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java
index f0ddc85..4542f2f 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMoveTest.java
@@ -33,6 +33,7 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper.FetchType;
@@ -47,7 +48,7 @@ public abstract class MessageMoveTest {
     private static final char DELIMITER = '.';
     private static final int LIMIT = 10;
     private static final int BODY_START = 16;
-    private static final int UID_VALIDITY = 42;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
 
     private MapperProvider mapperProvider;
     private MessageMapper messageMapper;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java
index b6d22de..f10a0b6 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageWithAttachmentMapperTest.java
@@ -40,6 +40,7 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageAttachment;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.mail.AttachmentMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
@@ -54,7 +55,7 @@ public abstract class MessageWithAttachmentMapperTest {
 
     private static final int LIMIT = 10;
     private static final int BODY_START = 16;
-    private static final int UID_VALIDITY = 42;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(42);
 
     private MapperProvider mapperProvider;
     private MessageMapper messageMapper;
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java
index 283945a..d744e15 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultUserQuotaRootResolverTest.java
@@ -36,6 +36,7 @@ import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.model.TestId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
 import org.junit.jupiter.api.BeforeEach;
@@ -48,9 +49,9 @@ class DefaultUserQuotaRootResolverTest {
     static final Username BENWA = Username.of("benwa");
     static final MailboxId MAILBOX_ID = TestId.of(42);
     static final MailboxPath MAILBOX_PATH = MailboxPath.inbox(BENWA);
-    static final Mailbox MAILBOX = new Mailbox(MAILBOX_PATH, 10, MAILBOX_ID);
+    static final Mailbox MAILBOX = new Mailbox(MAILBOX_PATH, UidValidity.of(10), MAILBOX_ID);
     static final MailboxPath MAILBOX_PATH_2 = MailboxPath.forUser(BENWA, "test");
-    static final Mailbox MAILBOX_2 = new Mailbox(MAILBOX_PATH_2, 10, MAILBOX_ID);
+    static final Mailbox MAILBOX_2 = new Mailbox(MAILBOX_PATH_2, UidValidity.of(10), MAILBOX_ID);
     static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("#private&benwa", Optional.empty());
     static final MailboxSession MAILBOX_SESSION = null;
 
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
index b162050..9c09ab2 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
@@ -38,6 +38,7 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.Quota;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.model.TestId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.junit.jupiter.api.BeforeEach;
@@ -48,7 +49,7 @@ class QuotaCheckerTest {
     static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("benwa", Optional.empty());
     static final MailboxId MAILBOX_ID = TestId.of(42);
     static final MailboxPath MAILBOX_PATH = MailboxPath.inbox(Username.of("benwa"));
-    static final Mailbox MAILBOX = new Mailbox(MAILBOX_PATH, 10, MAILBOX_ID);
+    static final Mailbox MAILBOX = new Mailbox(MAILBOX_PATH, UidValidity.of(10), MAILBOX_ID);
 
     QuotaRootResolver mockedQuotaRootResolver;
     QuotaManager mockedQuotaManager;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/api/message/response/StatusResponse.java b/protocols/imap/src/main/java/org/apache/james/imap/api/message/response/StatusResponse.java
index 4066bef..71eaf13 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/api/message/response/StatusResponse.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/api/message/response/StatusResponse.java
@@ -36,6 +36,7 @@ import org.apache.james.imap.api.message.MessageFlags;
 import org.apache.james.imap.api.message.UidRange;
 import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.ModSeq;
+import org.apache.james.mailbox.model.UidValidity;
 
 import com.github.steveash.guavate.Guavate;
 
@@ -150,17 +151,17 @@ public interface StatusResponse extends ImapResponseMessage {
 
         
         /** RFC4315 <code>APPENDUID</code> response code */
-        public static ResponseCode appendUid(long uidValidity, UidRange[] uids) {
+        public static ResponseCode appendUid(UidValidity uidValidity, UidRange[] uids) {
             String uidParam = formatRanges(uids);
-            return new ResponseCode("APPENDUID", Arrays.asList(uidParam), uidValidity, false);
+            return new ResponseCode("APPENDUID", Arrays.asList(uidParam), uidValidity.asLong(), false);
         }
 
         /** RFC4315 <code>COPYUID</code> response code */
-        public static ResponseCode copyUid(long uidValidity, IdRange[] sourceRanges, IdRange[] targetRanges) {
+        public static ResponseCode copyUid(UidValidity uidValidity, IdRange[] sourceRanges, IdRange[] targetRanges) {
             String source = formatRanges(sourceRanges);
             String target = formatRanges(targetRanges);
 
-            return new ResponseCode("COPYUID", Arrays.asList(new String[] { source, target }), uidValidity, false);
+            return new ResponseCode("COPYUID", Arrays.asList(new String[] { source, target }), uidValidity.asLong(), false);
         }
 
         /** RFC4551 <code>Conditional STORE</code> response code */
@@ -287,8 +288,8 @@ public interface StatusResponse extends ImapResponseMessage {
          *            positive non-zero integer
          * @return <code>ResponseCode</code>, not null
          */
-        public static ResponseCode uidValidity(long uid) {
-            return new ResponseCode("UIDVALIDITY", uid);
+        public static ResponseCode uidValidity(UidValidity uid) {
+            return new ResponseCode("UIDVALIDITY", uid.asLong());
         }
 
         /**
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java
index 3933c5e..71b41d0 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AbstractSelectionCommandParser.java
@@ -33,6 +33,7 @@ import org.apache.james.imap.decode.ImapRequestLineReader.StringMatcherCharacter
 import org.apache.james.imap.decode.base.AbstractImapCommandParser;
 import org.apache.james.imap.message.request.AbstractMailboxSelectionRequest;
 import org.apache.james.mailbox.MessageUid;
+import org.apache.james.mailbox.model.UidValidity;
 
 public abstract class AbstractSelectionCommandParser extends AbstractImapCommandParser {
     private static final String CONDSTORE = ImapConstants.SUPPORTS_CONDSTORE.asString();
@@ -46,7 +47,7 @@ public abstract class AbstractSelectionCommandParser extends AbstractImapCommand
     protected ImapMessage decode(ImapRequestLineReader request, Tag tag, ImapSession session) throws DecodingException {
         final String mailboxName = request.mailbox();
         boolean condstore = false;
-        Long lastKnownUidValidity = null;
+        UidValidity lastKnownUidValidity = null;
         Long knownModSeq = null;
         UidRange[] uidSet = null;
         UidRange[] knownUidSet = null;
@@ -79,7 +80,7 @@ public abstract class AbstractSelectionCommandParser extends AbstractImapCommand
                 
                 // Consume enclosing paren
                 request.consumeChar('(');
-                lastKnownUidValidity = request.number();
+                lastKnownUidValidity = UidValidity.of(request.number());
                 
                 // Consume the SP
                 request.consumeChar(' ');
@@ -206,5 +207,5 @@ public abstract class AbstractSelectionCommandParser extends AbstractImapCommand
     /**
      * Create a new {@link AbstractMailboxSelectionRequest} for the given arguments
      */
-    protected abstract AbstractMailboxSelectionRequest createRequest(String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag);
+    protected abstract AbstractMailboxSelectionRequest createRequest(String mailboxName, boolean condstore, UidValidity lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag);
 }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
index bc71492..b2bef7e 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
@@ -25,6 +25,7 @@ import org.apache.james.imap.api.message.UidRange;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.message.request.AbstractMailboxSelectionRequest;
 import org.apache.james.imap.message.request.ExamineRequest;
+import org.apache.james.mailbox.model.UidValidity;
 
 /**
  * Parse EXAMINE commands
@@ -36,7 +37,7 @@ public class ExamineCommandParser extends AbstractSelectionCommandParser {
     }
 
     @Override
-    protected AbstractMailboxSelectionRequest createRequest(String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag) {
+    protected AbstractMailboxSelectionRequest createRequest(String mailboxName, boolean condstore, UidValidity lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag) {
         return new ExamineRequest(mailboxName, condstore, lastKnownUidValidity, knownModSeq, uidSet, knownUidSet, knownSequenceSet, tag);
     }
 }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java
index 8fc5dc8..dd30d44 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java
@@ -25,6 +25,7 @@ import org.apache.james.imap.api.message.UidRange;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.message.request.AbstractMailboxSelectionRequest;
 import org.apache.james.imap.message.request.SelectRequest;
+import org.apache.james.mailbox.model.UidValidity;
 
 /**
  * Parse SELECT commands
@@ -35,7 +36,7 @@ public class SelectCommandParser extends AbstractSelectionCommandParser {
     }
 
     @Override
-    protected AbstractMailboxSelectionRequest createRequest(String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag) {
+    protected AbstractMailboxSelectionRequest createRequest(String mailboxName, boolean condstore, UidValidity lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag) {
         return new SelectRequest(mailboxName, condstore, lastKnownUidValidity, knownModSeq, uidSet, knownUidSet, knownSequenceSet, tag);
     }
 }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/MailboxStatusResponseEncoder.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/MailboxStatusResponseEncoder.java
index 2f64f67..be913d6 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/encode/MailboxStatusResponseEncoder.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/MailboxStatusResponseEncoder.java
@@ -25,6 +25,7 @@ import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.message.response.MailboxStatusResponse;
 import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.ModSeq;
+import org.apache.james.mailbox.model.UidValidity;
 
 /**
  * Encodes <code>STATUS</code> responses.
@@ -41,7 +42,7 @@ public class MailboxStatusResponseEncoder implements ImapConstants, ImapResponse
         Long recent = response.getRecent();
         MessageUid uidNext = response.getUidNext();
         ModSeq highestModSeq = response.getHighestModSeq();
-        Long uidValidity = response.getUidValidity();
+        UidValidity uidValidity = response.getUidValidity();
         Long unseen = response.getUnseen();
         String mailboxName = response.getMailbox();
 
@@ -75,8 +76,8 @@ public class MailboxStatusResponseEncoder implements ImapConstants, ImapResponse
 
         if (uidValidity != null) {
             composer.message(STATUS_UIDVALIDITY);
-            final long uidValidityValue = uidValidity;
-            composer.message(uidValidityValue);
+            final UidValidity uidValidityValue = uidValidity;
+            composer.message(uidValidityValue.asLong());
         }
 
         if (unseen != null) {
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java b/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java
index 137c17e..468e2b0 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractMailboxSelectionRequest.java
@@ -24,6 +24,7 @@ import org.apache.james.imap.api.Tag;
 import org.apache.james.imap.api.message.IdRange;
 import org.apache.james.imap.api.message.UidRange;
 import org.apache.james.imap.api.message.request.ImapRequest;
+import org.apache.james.mailbox.model.UidValidity;
 
 /**
  * {@link ImapRequest} which selects a Mailbox. 
@@ -35,13 +36,13 @@ public abstract class AbstractMailboxSelectionRequest extends AbstractImapReques
 
     private final String mailboxName;
     private final boolean condstore;
-    private final Long lastKnownUidValidity;
+    private final UidValidity lastKnownUidValidity;
     private final Long knownModSeq;
     private final UidRange[] uidSet;
     private final UidRange[] knownUidSet;
     private final IdRange[] knownSequenceSet;
 
-    public AbstractMailboxSelectionRequest(ImapCommand command, String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag) {
+    public AbstractMailboxSelectionRequest(ImapCommand command, String mailboxName, boolean condstore, UidValidity lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag) {
         super(tag, command);
         this.mailboxName = mailboxName;
         this.condstore = condstore;
@@ -79,7 +80,7 @@ public abstract class AbstractMailboxSelectionRequest extends AbstractImapReques
      * 
      * @return lastKnownUidValidity
      */
-    public final Long getLastKnownUidValidity() {
+    public final UidValidity getLastKnownUidValidity() {
         return lastKnownUidValidity;
     }
     
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java b/protocols/imap/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java
index 0d81852..a3989e8 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/message/request/ExamineRequest.java
@@ -22,9 +22,10 @@ import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.Tag;
 import org.apache.james.imap.api.message.IdRange;
 import org.apache.james.imap.api.message.UidRange;
+import org.apache.james.mailbox.model.UidValidity;
 
 public class ExamineRequest extends AbstractMailboxSelectionRequest {
-    public ExamineRequest(String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag) {
+    public ExamineRequest(String mailboxName, boolean condstore, UidValidity lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag) {
         super(ImapConstants.EXAMINE_COMMAND, mailboxName, condstore, lastKnownUidValidity, knownModSeq, uidSet, knownUidSet, knownSequenceSet, tag);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/request/SelectRequest.java b/protocols/imap/src/main/java/org/apache/james/imap/message/request/SelectRequest.java
index 44aa85e..b8bf1a3 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/message/request/SelectRequest.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/message/request/SelectRequest.java
@@ -22,9 +22,10 @@ import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.Tag;
 import org.apache.james.imap.api.message.IdRange;
 import org.apache.james.imap.api.message.UidRange;
+import org.apache.james.mailbox.model.UidValidity;
 
 public class SelectRequest extends AbstractMailboxSelectionRequest {
-    public SelectRequest(String mailboxName, boolean condstore, Long lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag) {
+    public SelectRequest(String mailboxName, boolean condstore, UidValidity lastKnownUidValidity, Long knownModSeq, UidRange[] uidSet, UidRange[] knownUidSet, IdRange[] knownSequenceSet, Tag tag) {
         super(ImapConstants.SELECT_COMMAND, mailboxName, condstore, lastKnownUidValidity, knownModSeq, uidSet, knownUidSet, knownSequenceSet, tag);
     }
 }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/response/MailboxStatusResponse.java b/protocols/imap/src/main/java/org/apache/james/imap/message/response/MailboxStatusResponse.java
index c7798b3..7282ca7 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/message/response/MailboxStatusResponse.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/message/response/MailboxStatusResponse.java
@@ -22,6 +22,7 @@ package org.apache.james.imap.message.response;
 import org.apache.james.imap.api.message.response.ImapResponseMessage;
 import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.ModSeq;
+import org.apache.james.mailbox.model.UidValidity;
 
 /**
  * Represents a <code>STATUS</code> response. See <code>RFC3501 7.2.4</code>.
@@ -30,12 +31,12 @@ public class MailboxStatusResponse implements ImapResponseMessage {
     private final Long messages;
     private final Long recent;
     private final MessageUid uidNext;
-    private final Long uidValidity;
+    private final UidValidity uidValidity;
     private final Long unseen;
     private final String mailbox;
     private final ModSeq highestModSeq;
 
-    public MailboxStatusResponse(Long messages, Long recent, MessageUid uidNext, ModSeq highestModSeq, Long uidValidity, Long unseen, String mailbox) {
+    public MailboxStatusResponse(Long messages, Long recent, MessageUid uidNext, ModSeq highestModSeq, UidValidity uidValidity, Long unseen, String mailbox) {
         super();
         this.messages = messages;
         this.recent = recent;
@@ -79,7 +80,7 @@ public class MailboxStatusResponse implements ImapResponseMessage {
      * 
      * @return the mailbox uidValidity (if requested) or null (if not)
      */
-    public final Long getUidValidity() {
+    public final UidValidity getUidValidity() {
         return uidValidity;
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java
index 8860c1a..0d3e1f3 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMessageRangeProcessor.java
@@ -40,6 +40,7 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MessageRangeException;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.metrics.api.MetricFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -104,7 +105,7 @@ public abstract class AbstractMessageRangeProcessor<R extends AbstractMessageRan
             .toArray(new IdRange[0]);
 
         // get folder UIDVALIDITY
-        Long uidValidity = mailbox.getMailboxEntity().getUidValidity();
+        UidValidity uidValidity = mailbox.getMailboxEntity().getUidValidity();
 
         return StatusResponse.ResponseCode.copyUid(uidValidity, request.getIdSet(), resultUids);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
index f00345e..e243fdf 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
@@ -54,6 +54,7 @@ import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.exception.MessageRangeException;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.metrics.api.MetricFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -96,8 +97,8 @@ abstract class AbstractSelectionProcessor<R extends AbstractMailboxSelectionRequ
     }
 
     private void respond(ImapSession session, MailboxPath fullMailboxPath, AbstractMailboxSelectionRequest request, Responder responder) throws MailboxException, MessageRangeException {
-        
-        Long lastKnownUidValidity = request.getLastKnownUidValidity();
+
+        UidValidity lastKnownUidValidity = request.getLastKnownUidValidity();
         Long modSeq = request.getKnownModSeq();
         IdRange[] knownSequences = request.getKnownSequenceSet();
         UidRange[] knownUids = request.getKnownUidSet();
@@ -363,7 +364,7 @@ abstract class AbstractSelectionProcessor<R extends AbstractMailboxSelectionRequ
     }
 
     private void uidValidity(Responder responder, MessageManager.MetaData metaData) throws MailboxException {
-        final long uidValidity = metaData.getUidValidity();
+        final UidValidity uidValidity = metaData.getUidValidity();
         final StatusResponse untaggedOk = statusResponseFactory.untaggedOk(HumanReadableText.UID_VALIDITY, ResponseCode.uidValidity(uidValidity));
         responder.respond(untaggedOk);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java
index 707a356..fd869cb 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java
@@ -46,6 +46,7 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.ComposedMessageId;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.util.MDCBuilder;
 import org.slf4j.Logger;
@@ -133,7 +134,7 @@ public class AppendProcessor extends AbstractMailboxProcessor<AppendRequest> {
             }
 
             // get folder UIDVALIDITY
-            Long uidValidity = mailboxManager.getMailbox(mailboxPath, mailboxSession)
+            UidValidity uidValidity = mailboxManager.getMailbox(mailboxPath, mailboxSession)
                 .getMailboxEntity()
                 .getUidValidity();
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/ExamineProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExamineProcessor.java
index 5486524..0468251 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/ExamineProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExamineProcessor.java
@@ -20,6 +20,7 @@
 package org.apache.james.imap.processor;
 
 import java.io.Closeable;
+import java.util.Optional;
 
 import org.apache.james.imap.api.message.IdRange;
 import org.apache.james.imap.api.message.UidRange;
@@ -28,6 +29,7 @@ import org.apache.james.imap.api.process.ImapProcessor;
 import org.apache.james.imap.message.request.ExamineRequest;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.events.EventBus;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.util.MDCBuilder;
 
@@ -47,7 +49,8 @@ public class ExamineProcessor extends AbstractSelectionProcessor<ExamineRequest>
             .addContext("knownModseq", request.getKnownModSeq())
             .addContext("knownUids", UidRange.toString(request.getKnownUidSet()))
             .addContext("knownIdRange", IdRange.toString(request.getKnownSequenceSet()))
-            .addContext("lastKnownUidValidity", request.getLastKnownUidValidity())
+            .addContext("lastKnownUidValidity", Optional.ofNullable(request.getLastKnownUidValidity())
+                .map(UidValidity::asLong))
             .addContext("uidSet", UidRange.toString(request.getUidSet()))
             .build();
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/SelectProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/SelectProcessor.java
index 6d9bb18..12a67aa 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/SelectProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/SelectProcessor.java
@@ -20,6 +20,7 @@
 package org.apache.james.imap.processor;
 
 import java.io.Closeable;
+import java.util.Optional;
 
 import org.apache.james.imap.api.message.IdRange;
 import org.apache.james.imap.api.message.UidRange;
@@ -28,6 +29,7 @@ import org.apache.james.imap.api.process.ImapProcessor;
 import org.apache.james.imap.message.request.SelectRequest;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.events.EventBus;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.util.MDCBuilder;
 
@@ -47,7 +49,8 @@ public class SelectProcessor extends AbstractSelectionProcessor<SelectRequest> {
             .addContext("knownModseq", message.getKnownModSeq())
             .addContext("knownUids", UidRange.toString(message.getKnownUidSet()))
             .addContext("knownIdRange", IdRange.toString(message.getKnownSequenceSet()))
-            .addContext("lastKnownUidValidity", message.getLastKnownUidValidity())
+            .addContext("lastKnownUidValidity", Optional.ofNullable(message.getLastKnownUidValidity())
+                .map(UidValidity::asLong))
             .addContext("uidSet", UidRange.toString(message.getUidSet()))
             .build();
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
index cf2aade..292269a 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
@@ -36,6 +36,7 @@ import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.ModSeq;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.util.MDCBuilder;
 import org.slf4j.Logger;
@@ -85,7 +86,7 @@ public class StatusProcessor extends AbstractMailboxProcessor<StatusRequest> {
         Long messages = messages(statusDataItems, metaData);
         Long recent = recent(statusDataItems, metaData);
         MessageUid uidNext = uidNext(statusDataItems, metaData);
-        Long uidValidity = uidValidity(statusDataItems, metaData);
+        UidValidity uidValidity = uidValidity(statusDataItems, metaData);
         Long unseen = unseen(statusDataItems, metaData);
         ModSeq highestModSeq = highestModSeq(statusDataItems, metaData);
         return new MailboxStatusResponse(messages, recent, uidNext, highestModSeq, uidValidity, unseen, request.getMailboxName());
@@ -107,7 +108,7 @@ public class StatusProcessor extends AbstractMailboxProcessor<StatusRequest> {
         }
     }
 
-    private Long uidValidity(StatusDataItems statusDataItems, MessageManager.MetaData metaData) {
+    private UidValidity uidValidity(StatusDataItems statusDataItems, MessageManager.MetaData metaData) {
         if (statusDataItems.isUidValidity()) {
             return metaData.getUidValidity();
         } else {
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/encode/MailboxStatusResponseEncoderTest.java b/protocols/imap/src/test/java/org/apache/james/imap/encode/MailboxStatusResponseEncoderTest.java
index facc364..110feee 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/encode/MailboxStatusResponseEncoderTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/encode/MailboxStatusResponseEncoderTest.java
@@ -25,6 +25,7 @@ import org.apache.james.imap.encode.base.ByteImapResponseWriter;
 import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
 import org.apache.james.imap.message.response.MailboxStatusResponse;
 import org.apache.james.mailbox.MessageUid;
+import org.apache.james.mailbox.model.UidValidity;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -50,7 +51,7 @@ public class MailboxStatusResponseEncoderTest  {
         final Long messages = 2L;
         final Long recent = 3L;
         final MessageUid uidNext = MessageUid.of(5);
-        final Long uidValidity = 7L;
+        final UidValidity uidValidity = UidValidity.of(7L);
         final Long unseen = 11L;
         final String mailbox = "A mailbox named desire";
 
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java
index 3af65df..61a7580 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java
@@ -50,6 +50,7 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
@@ -97,7 +98,7 @@ public class CopyProcessorTest {
         MessageManager targetMessageManager = mock(MessageManager.class);
         when(mockMailboxManager.getMailbox(INBOX, mailboxSession)).thenReturn(targetMessageManager);
         Mailbox mailbox = mock(Mailbox.class);
-        when(mailbox.getUidValidity()).thenReturn(58L);
+        when(mailbox.getUidValidity()).thenReturn(UidValidity.of(58L));
         when(targetMessageManager.getMailboxEntity()).thenReturn(mailbox);
         StatusResponse okResponse = mock(StatusResponse.class);
         when(mockStatusResponseFactory.taggedOk(any(Tag.class), any(ImapCommand.class), any(HumanReadableText.class), any(StatusResponse.ResponseCode.class))).thenReturn(okResponse);
@@ -130,7 +131,7 @@ public class CopyProcessorTest {
         MessageManager targetMessageManager = mock(MessageManager.class);
         when(mockMailboxManager.getMailbox(INBOX, mailboxSession)).thenReturn(targetMessageManager);
         Mailbox mailbox = mock(Mailbox.class);
-        when(mailbox.getUidValidity()).thenReturn(58L);
+        when(mailbox.getUidValidity()).thenReturn(UidValidity.of(58L));
         when(targetMessageManager.getMailboxEntity()).thenReturn(mailbox);
         StatusResponse okResponse = mock(StatusResponse.class);
         when(mockStatusResponseFactory.taggedOk(any(Tag.class), any(ImapCommand.class), any(HumanReadableText.class), any(StatusResponse.ResponseCode.class))).thenReturn(okResponse);
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java
index 20515cb..3fafe5c 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java
@@ -53,6 +53,7 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
@@ -113,7 +114,7 @@ public class MoveProcessorTest {
         MessageManager targetMessageManager = mock(MessageManager.class);
         when(mockMailboxManager.getMailbox(INBOX, mailboxSession)).thenReturn(targetMessageManager);
         Mailbox mailbox = mock(Mailbox.class);
-        when(mailbox.getUidValidity()).thenReturn(58L);
+        when(mailbox.getUidValidity()).thenReturn(UidValidity.of(58L));
         when(targetMessageManager.getMailboxEntity()).thenReturn(mailbox);
         StatusResponse okResponse = mock(StatusResponse.class);
         when(mockStatusResponseFactory.taggedOk(any(Tag.class), any(ImapCommand.class), any(HumanReadableText.class), any(StatusResponse.ResponseCode.class))).thenReturn(okResponse);
@@ -146,7 +147,7 @@ public class MoveProcessorTest {
         MessageManager targetMessageManager = mock(MessageManager.class);
         when(mockMailboxManager.getMailbox(INBOX, mailboxSession)).thenReturn(targetMessageManager);
         Mailbox mailbox = mock(Mailbox.class);
-        when(mailbox.getUidValidity()).thenReturn(58L);
+        when(mailbox.getUidValidity()).thenReturn(UidValidity.of(58L));
         when(targetMessageManager.getMailboxEntity()).thenReturn(mailbox);
         StatusResponse okResponse = mock(StatusResponse.class);
         when(mockStatusResponseFactory.taggedOk(any(Tag.class), any(ImapCommand.class), any(HumanReadableText.class), any(StatusResponse.ResponseCode.class))).thenReturn(okResponse);
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java
index 4c885ba..736a0f3 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java
@@ -50,6 +50,7 @@ import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageResult;
 import org.apache.james.mailbox.model.MessageResultIterator;
 import org.apache.james.mailbox.model.TestId;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.store.event.EventFactory;
 import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
@@ -116,7 +117,7 @@ public class MailboxEventAnalyserTest {
     private static final char PATH_DELIMITER = '.';
     private static final MailboxPath MAILBOX_PATH = new MailboxPath("namespace", USER, "name");
     private static final TestId MAILBOX_ID = TestId.of(36);
-    private static final int UID_VALIDITY = 1024;
+    private static final UidValidity UID_VALIDITY = UidValidity.of(1024);
     private static final Mailbox DEFAULT_MAILBOX = new Mailbox(MAILBOX_PATH, UID_VALIDITY, MAILBOX_ID);
     private static final MailboxListener.Added ADDED = EventFactory.added()
         .randomEventId()
diff --git a/server/container/mailbox-jmx/src/test/java/org/apache/james/adapter/mailbox/MailboxManagementTest.java b/server/container/mailbox-jmx/src/test/java/org/apache/james/adapter/mailbox/MailboxManagementTest.java
index c1ab9e9..21c33c7 100644
--- a/server/container/mailbox-jmx/src/test/java/org/apache/james/adapter/mailbox/MailboxManagementTest.java
+++ b/server/container/mailbox-jmx/src/test/java/org/apache/james/adapter/mailbox/MailboxManagementTest.java
@@ -36,6 +36,7 @@ import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
 import org.apache.james.mailbox.store.StoreMailboxManager;
 import org.apache.james.mailbox.store.mail.MailboxMapper;
@@ -47,7 +48,7 @@ import org.junit.jupiter.api.Test;
 public class MailboxManagementTest {
 
     public static final Username USER = Username.of("user");
-    public static final int UID_VALIDITY = 10;
+    public static final UidValidity UID_VALIDITY = UidValidity.of(10);
     public static final int LIMIT = 1;
 
     private MailboxManagerManagement mailboxManagerManagement;
diff --git a/server/protocols/protocols-pop3/src/main/java/org/apache/james/pop3server/mailbox/MailboxAdapter.java b/server/protocols/protocols-pop3/src/main/java/org/apache/james/pop3server/mailbox/MailboxAdapter.java
index a1234d0..9d66b9b 100644
--- a/server/protocols/protocols-pop3/src/main/java/org/apache/james/pop3server/mailbox/MailboxAdapter.java
+++ b/server/protocols/protocols-pop3/src/main/java/org/apache/james/pop3server/mailbox/MailboxAdapter.java
@@ -1,174 +1,175 @@
-/****************************************************************
- * 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.pop3server.mailbox;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.apache.james.mailbox.MailboxManager;
-import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.MessageManager;
-import org.apache.james.mailbox.MessageUid;
-import org.apache.james.mailbox.exception.MailboxException;
-import org.apache.james.mailbox.model.FetchGroup;
-import org.apache.james.mailbox.model.MessageRange;
-import org.apache.james.mailbox.model.MessageResult;
-import org.apache.james.protocols.pop3.mailbox.Mailbox;
-import org.apache.james.protocols.pop3.mailbox.MessageMetaData;
-
-import com.github.steveash.guavate.Guavate;
-import com.google.common.collect.ImmutableList;
-
-public class MailboxAdapter implements Mailbox {
-    private static final FetchGroup FULL_GROUP = FetchGroup.FULL_CONTENT;
-    private static final FetchGroup BODY_GROUP = FetchGroup.BODY_CONTENT;
-    private static final FetchGroup HEADERS_GROUP = FetchGroup.HEADERS;
-    private static final FetchGroup METADATA_GROUP = FetchGroup.MINIMAL;
-
-    private final MessageManager manager;
-    private final MailboxSession session;
-
-    private final MailboxManager mailboxManager;
-
-    public MailboxAdapter(MailboxManager mailboxManager, MessageManager manager, MailboxSession session) {
-        this.manager = manager;
-        this.session = session;
-        this.mailboxManager = mailboxManager;
-    }
-
-    @Override
-    public InputStream getMessageBody(String uid) throws IOException {
-        try {
-            mailboxManager.startProcessingRequest(session);
-            Iterator<MessageResult> results = manager.getMessages(MessageUid.of(Long.parseLong(uid)).toRange(), BODY_GROUP, session);
-            if (results.hasNext()) {
-                return results.next().getBody().getInputStream();
-            } else {
-                return null;
-            }
-        } catch (MailboxException e) {
-            throw new IOException("Unable to retrieve message body for uid " + uid, e);
-        } finally {
-            mailboxManager.endProcessingRequest(session);
-        }
-    }
-
-    @Override
-    public InputStream getMessageHeaders(String uid) throws IOException {
-        try {
-            mailboxManager.startProcessingRequest(session);
-            Iterator<MessageResult> results = manager.getMessages(MessageUid.of(Long.parseLong(uid)).toRange(), HEADERS_GROUP,
-                    session);
-            if (results.hasNext()) {
-                return results.next().getHeaders().getInputStream();
-            } else {
-                return null;
-            }
-        } catch (MailboxException e) {
-            throw new IOException("Unable to retrieve message header for uid " + uid, e);
-        } finally {
-            mailboxManager.endProcessingRequest(session);
-        }
-    }
-
-    @Override
-    public InputStream getMessage(String uid) throws IOException {
-        try {
-            mailboxManager.startProcessingRequest(session);
-            Iterator<MessageResult> results = manager.getMessages(MessageUid.of(Long.parseLong(uid)).toRange(), FULL_GROUP, session);
-            if (results.hasNext()) {
-                return results.next().getFullContent().getInputStream();
-            } else {
-                return null;
-            }
-        } catch (MailboxException e) {
-            throw new IOException("Unable to retrieve message for uid " + uid, e);
-        } finally {
-            mailboxManager.endProcessingRequest(session);
-        }
-    }
-
-    @Override
-    public List<MessageMetaData> getMessages() throws IOException {
-        try {
-            mailboxManager.startProcessingRequest(session);
-            Iterator<MessageResult> results = manager.getMessages(MessageRange.all(), METADATA_GROUP, session);
-            List<MessageMetaData> mList = new ArrayList<>();
-            while (results.hasNext()) {
-                MessageResult result = results.next();
-                MessageMetaData metaData = new MessageMetaData(String.valueOf(result.getUid().asLong()), result.getSize());
-                mList.add(metaData);
-            }
-            return ImmutableList.copyOf(mList);
-        } catch (MailboxException e) {
-            throw new IOException("Unable to retrieve messages", e);
-        } finally {
-            mailboxManager.endProcessingRequest(session);
-        }
-    }
-
-    @Override
-    public void remove(String... uids) throws IOException {
-        List<MessageUid> uidList = Arrays.stream(uids)
-            .map(uid -> MessageUid.of(Long.parseLong(uid)))
-            .collect(Guavate.toImmutableList());
-
-        try {
-            mailboxManager.startProcessingRequest(session);
-            manager.delete(uidList, session);
-        } catch (MailboxException e) {
-            String serializedUids = uidList
-                .stream()
-                .map(uid -> uid.toString())
-                .collect(Collectors.joining(",", "[", "]"));
-
-            throw new IOException("Unable to remove messages: " + serializedUids, e);
-        } finally {
-            mailboxManager.endProcessingRequest(session);
-        }
-    }
-
-    @Override
-    public String getIdentifier() throws IOException {
-        try {
-            mailboxManager.startProcessingRequest(session);
-            long validity = manager.getMailboxEntity()
-                    .getUidValidity();
-            return Long.toString(validity);
-        } catch (MailboxException e) {
-            throw new IOException("Unable to retrieve indentifier for mailbox", e);
-        } finally {
-            mailboxManager.endProcessingRequest(session);
-        }
-    }
-
-    @Override
-    public void close() throws IOException {
-        try {
-            mailboxManager.logout(session);
-        } finally {
-            mailboxManager.endProcessingRequest(session);
-        }
-    }
-}
+/****************************************************************
+ * 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.pop3server.mailbox;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.MessageUid;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.FetchGroup;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.MessageResult;
+import org.apache.james.protocols.pop3.mailbox.Mailbox;
+import org.apache.james.protocols.pop3.mailbox.MessageMetaData;
+
+import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableList;
+
+public class MailboxAdapter implements Mailbox {
+    private static final FetchGroup FULL_GROUP = FetchGroup.FULL_CONTENT;
+    private static final FetchGroup BODY_GROUP = FetchGroup.BODY_CONTENT;
+    private static final FetchGroup HEADERS_GROUP = FetchGroup.HEADERS;
+    private static final FetchGroup METADATA_GROUP = FetchGroup.MINIMAL;
+
+    private final MessageManager manager;
+    private final MailboxSession session;
+
+    private final MailboxManager mailboxManager;
+
+    public MailboxAdapter(MailboxManager mailboxManager, MessageManager manager, MailboxSession session) {
+        this.manager = manager;
+        this.session = session;
+        this.mailboxManager = mailboxManager;
+    }
+
+    @Override
+    public InputStream getMessageBody(String uid) throws IOException {
+        try {
+            mailboxManager.startProcessingRequest(session);
+            Iterator<MessageResult> results = manager.getMessages(MessageUid.of(Long.parseLong(uid)).toRange(), BODY_GROUP, session);
+            if (results.hasNext()) {
+                return results.next().getBody().getInputStream();
+            } else {
+                return null;
+            }
+        } catch (MailboxException e) {
+            throw new IOException("Unable to retrieve message body for uid " + uid, e);
+        } finally {
+            mailboxManager.endProcessingRequest(session);
+        }
+    }
+
+    @Override
+    public InputStream getMessageHeaders(String uid) throws IOException {
+        try {
+            mailboxManager.startProcessingRequest(session);
+            Iterator<MessageResult> results = manager.getMessages(MessageUid.of(Long.parseLong(uid)).toRange(), HEADERS_GROUP,
+                    session);
+            if (results.hasNext()) {
+                return results.next().getHeaders().getInputStream();
+            } else {
+                return null;
+            }
+        } catch (MailboxException e) {
+            throw new IOException("Unable to retrieve message header for uid " + uid, e);
+        } finally {
+            mailboxManager.endProcessingRequest(session);
+        }
+    }
+
+    @Override
+    public InputStream getMessage(String uid) throws IOException {
+        try {
+            mailboxManager.startProcessingRequest(session);
+            Iterator<MessageResult> results = manager.getMessages(MessageUid.of(Long.parseLong(uid)).toRange(), FULL_GROUP, session);
+            if (results.hasNext()) {
+                return results.next().getFullContent().getInputStream();
+            } else {
+                return null;
+            }
+        } catch (MailboxException e) {
+            throw new IOException("Unable to retrieve message for uid " + uid, e);
+        } finally {
+            mailboxManager.endProcessingRequest(session);
+        }
+    }
+
+    @Override
+    public List<MessageMetaData> getMessages() throws IOException {
+        try {
+            mailboxManager.startProcessingRequest(session);
+            Iterator<MessageResult> results = manager.getMessages(MessageRange.all(), METADATA_GROUP, session);
+            List<MessageMetaData> mList = new ArrayList<>();
+            while (results.hasNext()) {
+                MessageResult result = results.next();
+                MessageMetaData metaData = new MessageMetaData(String.valueOf(result.getUid().asLong()), result.getSize());
+                mList.add(metaData);
+            }
+            return ImmutableList.copyOf(mList);
+        } catch (MailboxException e) {
+            throw new IOException("Unable to retrieve messages", e);
+        } finally {
+            mailboxManager.endProcessingRequest(session);
+        }
+    }
+
+    @Override
+    public void remove(String... uids) throws IOException {
+        List<MessageUid> uidList = Arrays.stream(uids)
+            .map(uid -> MessageUid.of(Long.parseLong(uid)))
+            .collect(Guavate.toImmutableList());
+
+        try {
+            mailboxManager.startProcessingRequest(session);
+            manager.delete(uidList, session);
+        } catch (MailboxException e) {
+            String serializedUids = uidList
+                .stream()
+                .map(uid -> uid.toString())
+                .collect(Collectors.joining(",", "[", "]"));
+
+            throw new IOException("Unable to remove messages: " + serializedUids, e);
+        } finally {
+            mailboxManager.endProcessingRequest(session);
+        }
+    }
+
+    @Override
+    public String getIdentifier() throws IOException {
+        try {
+            mailboxManager.startProcessingRequest(session);
+            long validity = manager.getMailboxEntity()
+                    .getUidValidity()
+                    .asLong();
+            return Long.toString(validity);
+        } catch (MailboxException e) {
+            throw new IOException("Unable to retrieve indentifier for mailbox", e);
+        } finally {
+            mailboxManager.endProcessingRequest(session);
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        try {
+            mailboxManager.logout(session);
+        } finally {
+            mailboxManager.endProcessingRequest(session);
+        }
+    }
+}


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


[james-project] 04/29: MAILBOX-396 Reduce query amount upon listing message

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 2e92b18c914ce58350240585e758c5e3237f773e
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Feb 26 09:29:18 2020 +0700

    MAILBOX-396 Reduce query amount upon listing message
    
    This can be achieved via a "groupBy" before keepMessageIfMailboxExists to
    only do one read per mailbox instead of one read per message.
---
 .../cassandra/mail/CassandraMessageIdMapper.java     | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
index 3a206c3..750b6bd 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
@@ -44,7 +44,6 @@ import org.apache.james.mailbox.store.mail.MessageMapper.FetchType;
 import org.apache.james.mailbox.store.mail.ModSeqProvider;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.apache.james.util.FunctionalUtils;
-import org.apache.james.util.ReactorUtils;
 import org.apache.james.util.streams.Limit;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -53,6 +52,7 @@ import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.Multimap;
 
 import reactor.core.publisher.Flux;
+import reactor.core.publisher.GroupedFlux;
 import reactor.core.publisher.Mono;
 import reactor.core.scheduler.Schedulers;
 
@@ -95,20 +95,22 @@ public class CassandraMessageIdMapper implements MessageIdMapper {
             .filter(CassandraMessageDAO.MessageResult::isFound)
             .map(CassandraMessageDAO.MessageResult::message)
             .flatMap(messageRepresentation -> attachmentLoader.addAttachmentToMessage(messageRepresentation, fetchType))
+            .groupBy(MailboxMessage::getMailboxId)
             .flatMap(this::keepMessageIfMailboxExists)
             .collectSortedList(Comparator.comparing(MailboxMessage::getUid))
             .block();
     }
 
-    private Mono<MailboxMessage> keepMessageIfMailboxExists(MailboxMessage message) {
-        CassandraId cassandraId = (CassandraId) message.getMailboxId();
+    private Flux<MailboxMessage> keepMessageIfMailboxExists(GroupedFlux<MailboxId, MailboxMessage> groupedFlux) {
+        CassandraId cassandraId = (CassandraId) groupedFlux.key();
         return mailboxDAO.retrieveMailbox(cassandraId)
-            .map(any -> message)
-            .switchIfEmpty(ReactorUtils.executeAndEmpty(() -> {
-                    LOGGER.info("Mailbox {} have been deleted but message {} is still attached to it.",
-                        cassandraId,
-                        message.getMailboxId());
-                }));
+            .flatMapMany(any -> groupedFlux)
+            .switchIfEmpty(groupedFlux.map(message -> {
+                LOGGER.info("Mailbox {} have been deleted but message {} is still attached to it.",
+                    cassandraId.serialize(),
+                    message.getMessageId().serialize());
+                return message;
+            }).then(Mono.empty()));
     }
 
     @Override


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