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

[james-project] 05/27: JAMES-3143 SolveMessageInconsistenciesTask/DTO

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 84374e53305d80483b09799537f22fc97c6fb2b9
Author: LanKhuat <kh...@gmail.com>
AuthorDate: Tue Apr 21 00:09:51 2020 +0700

    JAMES-3143 SolveMessageInconsistenciesTask/DTO
---
 .../mail/task/MessageInconsistenciesEntry.java     |  92 +++++++++++++
 .../mail/task/SolveMessageInconsistenciesTask.java | 143 +++++++++++++++++++++
 ...nconsistenciesTaskAdditionalInformationDTO.java | 135 +++++++++++++++++++
 .../task/SolveMessageInconsistenciesTaskDTO.java   |  60 +++++++++
 ...essageInconsistenciesTaskSerializationTest.java |  78 +++++++++++
 ...ssageInconsistencies.additionalInformation.json |  28 ++++
 .../json/solveMessageInconsistencies.task.json     |   3 +
 .../SolveMessageInconsistenciesRequestToTask.java  |  36 ++++++
 8 files changed, 575 insertions(+)

diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/MessageInconsistenciesEntry.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/MessageInconsistenciesEntry.java
new file mode 100644
index 0000000..0dec7f2
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/MessageInconsistenciesEntry.java
@@ -0,0 +1,92 @@
+/****************************************************************
+ * 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.cassandra.mail.task;
+
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class MessageInconsistenciesEntry {
+
+    public interface Builder {
+        @FunctionalInterface
+        interface RequireMailboxId {
+            RequireMessageId mailboxId(String mailboxId);
+        }
+
+        @FunctionalInterface
+        interface RequireMessageId {
+            RequireMessageUid messageId(String messageId);
+        }
+
+        @FunctionalInterface
+        interface RequireMessageUid {
+            MessageInconsistenciesEntry messageUid(Long messageUid);
+        }
+    }
+
+    public static Builder.RequireMailboxId builder() {
+        return mailboxId -> messageId -> messageUid -> new MessageInconsistenciesEntry(mailboxId, messageId, messageUid);
+    }
+
+    private final String mailboxId;
+    private final String messageId;
+    private final Long messageUid;
+
+    private MessageInconsistenciesEntry(@JsonProperty("mailboxId") String mailboxId,
+                                        @JsonProperty("messageId") String messageId,
+                                       @JsonProperty("uid") Long messageUid) {
+        this.mailboxId = mailboxId;
+        this.messageId = messageId;
+        this.messageUid = messageUid;
+    }
+
+    @JsonProperty("mailboxId")
+    public String getMailboxId() {
+        return mailboxId;
+    }
+
+    @JsonProperty("messageId")
+    public String getMessageId() {
+        return messageId;
+    }
+
+    @JsonProperty("uid")
+    public Long getMessageUid() {
+        return messageUid;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof MessageInconsistenciesEntry) {
+            MessageInconsistenciesEntry that = (MessageInconsistenciesEntry) o;
+
+            return Objects.equals(this.mailboxId, that.mailboxId)
+                && Objects.equals(this.messageId, that.messageId)
+                && Objects.equals(this.messageUid, that.messageUid);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(mailboxId, messageId, messageUid);
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTask.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTask.java
new file mode 100644
index 0000000..1fb540c
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTask.java
@@ -0,0 +1,143 @@
+/****************************************************************
+ * 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.cassandra.mail.task;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.util.Optional;
+
+import org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesService.Context;
+import org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesService.Context.Snapshot;
+import org.apache.james.mailbox.model.ComposedMessageId;
+import org.apache.james.task.Task;
+import org.apache.james.task.TaskExecutionDetails;
+import org.apache.james.task.TaskType;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableList;
+
+public class SolveMessageInconsistenciesTask implements Task {
+
+    static final TaskType SOLVE_MESSAGE_INCONSISTENCIES = TaskType.of("solve-message-inconsistencies");
+
+    public static class Details implements TaskExecutionDetails.AdditionalInformation {
+        private final Instant instant;
+        private final long processedImapUidEntries;
+        private final long processedMessageIdEntries;
+        private final long addedMessageIdEntries;
+        private final long updatedMessageIdEntries;
+        private final long removedMessageIdEntries;
+        private final ImmutableList<MessageInconsistenciesEntry> fixedInconsistencies;
+        private final ImmutableList<MessageInconsistenciesEntry> errors;
+
+        public Details(Instant instant, long processedImapUidEntries, long processedMessageIdEntries,
+                       long addedMessageIdEntries, long updatedMessageIdEntries, long removedMessageIdEntries,
+                       ImmutableList<MessageInconsistenciesEntry> fixedInconsistencies, ImmutableList<MessageInconsistenciesEntry> errors) {
+            this.instant = instant;
+            this.processedImapUidEntries = processedImapUidEntries;
+            this.processedMessageIdEntries = processedMessageIdEntries;
+            this.addedMessageIdEntries = addedMessageIdEntries;
+            this.updatedMessageIdEntries = updatedMessageIdEntries;
+            this.removedMessageIdEntries = removedMessageIdEntries;
+            this.fixedInconsistencies = fixedInconsistencies;
+            this.errors = errors;
+        }
+
+        @Override
+        public Instant timestamp() {
+            return instant;
+        }
+
+        @JsonProperty("processedImapUidEntries")
+        public long getProcessedImapUidEntries() {
+            return processedImapUidEntries;
+        }
+
+        @JsonProperty("processedMessageIdEntries")
+        public long getProcessedMessageIdEntries() {
+            return processedMessageIdEntries;
+        }
+
+        @JsonProperty("addedMessageIdEntries")
+        public long getAddedMessageIdEntries() {
+            return addedMessageIdEntries;
+        }
+
+        @JsonProperty("updatedMessageIdEntries")
+        public long getUpdatedMessageIdEntries() {
+            return updatedMessageIdEntries;
+        }
+
+        @JsonProperty("removedMessageIdEntries")
+        public long getRemovedMessageIdEntries() {
+            return removedMessageIdEntries;
+        }
+
+        @JsonProperty("fixedInconsistencies")
+        public ImmutableList<MessageInconsistenciesEntry> getFixedInconsistencies() {
+            return fixedInconsistencies;
+        }
+
+        @JsonProperty("errors")
+        public ImmutableList<MessageInconsistenciesEntry> getErrors() {
+            return errors;
+        }
+    }
+
+    private final SolveMessageInconsistenciesService service;
+    private Context context;
+
+    public SolveMessageInconsistenciesTask(SolveMessageInconsistenciesService service) {
+        this.service = service;
+        this.context = new Context();
+    }
+
+    @Override
+    public Result run() {
+        return service.fixMessageInconsistencies(context)
+            .block();
+    }
+
+    @Override
+    public TaskType type() {
+        return SOLVE_MESSAGE_INCONSISTENCIES;
+    }
+
+    @Override
+    public Optional<TaskExecutionDetails.AdditionalInformation> details() {
+        Snapshot snapshot = context.snapshot();
+        return Optional.of(new Details(Clock.systemUTC().instant(), snapshot.getProcessedImapUidEntries(), snapshot.getProcessedMessageIdEntries(),
+            snapshot.getAddedMessageIdEntries(), snapshot.getUpdatedMessageIdEntries(), snapshot.getRemovedMessageIdEntries(),
+            snapshot.getFixedInconsistencies().stream()
+                .map(this::toMessageInconsistenciesEntry)
+                .collect(Guavate.toImmutableList()),
+            snapshot.getErrors().stream()
+                .map(this::toMessageInconsistenciesEntry)
+                .collect(Guavate.toImmutableList())));
+    }
+
+    private MessageInconsistenciesEntry toMessageInconsistenciesEntry(ComposedMessageId composedMessageId) {
+        return MessageInconsistenciesEntry.builder()
+            .mailboxId(composedMessageId.getMailboxId().serialize())
+            .messageId(composedMessageId.getMessageId().serialize())
+            .messageUid(composedMessageId.getUid().asLong());
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTaskAdditionalInformationDTO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTaskAdditionalInformationDTO.java
new file mode 100644
index 0000000..a7792db
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTaskAdditionalInformationDTO.java
@@ -0,0 +1,135 @@
+/****************************************************************
+ * 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.cassandra.mail.task;
+
+import static org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesTask.SOLVE_MESSAGE_INCONSISTENCIES;
+
+import java.time.Instant;
+
+import org.apache.james.json.DTOModule;
+import org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesTask.Details;
+import org.apache.james.server.task.json.dto.AdditionalInformationDTO;
+import org.apache.james.server.task.json.dto.AdditionalInformationDTOModule;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.ImmutableList;
+
+public class SolveMessageInconsistenciesTaskAdditionalInformationDTO implements AdditionalInformationDTO {
+
+    private static SolveMessageInconsistenciesTaskAdditionalInformationDTO fromDomainObject(Details details, String type) {
+        return new SolveMessageInconsistenciesTaskAdditionalInformationDTO(
+            details.timestamp(),
+            type,
+            details.getProcessedImapUidEntries(),
+            details.getProcessedMessageIdEntries(),
+            details.getAddedMessageIdEntries(),
+            details.getUpdatedMessageIdEntries(),
+            details.getRemovedMessageIdEntries(),
+            details.getFixedInconsistencies(),
+            details.getErrors());
+    }
+
+    public static final AdditionalInformationDTOModule<Details, SolveMessageInconsistenciesTaskAdditionalInformationDTO> MODULE =
+        DTOModule
+            .forDomainObject(Details.class)
+            .convertToDTO(SolveMessageInconsistenciesTaskAdditionalInformationDTO.class)
+            .toDomainObjectConverter(SolveMessageInconsistenciesTaskAdditionalInformationDTO::toDomainObject)
+            .toDTOConverter(SolveMessageInconsistenciesTaskAdditionalInformationDTO::fromDomainObject)
+            .typeName(SOLVE_MESSAGE_INCONSISTENCIES.asString())
+            .withFactory(AdditionalInformationDTOModule::new);
+
+    private final Instant timestamp;
+    private final String type;
+    private final long processedImapUidEntries;
+    private final long processedMessageIdEntries;
+    private final long addedMessageIdEntries;
+    private final long updatedMessageIdEntries;
+    private final long removedMessageIdEntries;
+    private final ImmutableList<MessageInconsistenciesEntry> fixedInconsistencies;
+    private final ImmutableList<MessageInconsistenciesEntry> errors;
+
+    public SolveMessageInconsistenciesTaskAdditionalInformationDTO(@JsonProperty("timestamp") Instant timestamp, @JsonProperty("type") String type,
+                                                                   @JsonProperty("processedImapUidEntries") long processedImapUidEntries,
+                                                                   @JsonProperty("processedMessageIdEntries") long processedMessageIdEntries,
+                                                                   @JsonProperty("addedMessageIdEntries") long addedMessageIdEntries,
+                                                                   @JsonProperty("updatedMessageIdEntries") long updatedMessageIdEntries,
+                                                                   @JsonProperty("removedMessageIdEntries")long removedMessageIdEntries,
+                                                                   @JsonProperty("fixedInconsistencies") ImmutableList<MessageInconsistenciesEntry> fixedInconsistencies,
+                                                                   @JsonProperty("errors") ImmutableList<MessageInconsistenciesEntry> errors) {
+        this.timestamp = timestamp;
+        this.type = type;
+        this.processedImapUidEntries = processedImapUidEntries;
+        this.processedMessageIdEntries = processedMessageIdEntries;
+        this.addedMessageIdEntries = addedMessageIdEntries;
+        this.updatedMessageIdEntries = updatedMessageIdEntries;
+        this.removedMessageIdEntries = removedMessageIdEntries;
+        this.fixedInconsistencies = fixedInconsistencies;
+        this.errors = errors;
+    }
+
+    public long getProcessedImapUidEntries() {
+        return processedImapUidEntries;
+    }
+
+    public long getProcessedMessageIdEntries() {
+        return processedMessageIdEntries;
+    }
+
+    public long getAddedMessageIdEntries() {
+        return addedMessageIdEntries;
+    }
+
+    public long getUpdatedMessageIdEntries() {
+        return updatedMessageIdEntries;
+    }
+
+    public long getRemovedMessageIdEntries() {
+        return removedMessageIdEntries;
+    }
+
+    public ImmutableList<MessageInconsistenciesEntry> getFixedInconsistencies() {
+        return fixedInconsistencies;
+    }
+
+    public ImmutableList<MessageInconsistenciesEntry> getErrors() {
+        return errors;
+    }
+
+    @Override
+    public String getType() {
+        return this.type;
+    }
+
+    @Override
+    public Instant getTimestamp() {
+        return this.timestamp;
+    }
+
+    private Details toDomainObject() {
+        return new Details(timestamp,
+            processedImapUidEntries,
+            processedMessageIdEntries,
+            addedMessageIdEntries,
+            updatedMessageIdEntries,
+            removedMessageIdEntries,
+            fixedInconsistencies,
+            errors);
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTaskDTO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTaskDTO.java
new file mode 100644
index 0000000..7caeea6
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTaskDTO.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.mailbox.cassandra.mail.task;
+
+import static org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesTask.SOLVE_MESSAGE_INCONSISTENCIES;
+
+import org.apache.james.json.DTOModule;
+import org.apache.james.server.task.json.dto.TaskDTO;
+import org.apache.james.server.task.json.dto.TaskDTOModule;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class SolveMessageInconsistenciesTaskDTO implements TaskDTO {
+
+    private static SolveMessageInconsistenciesTaskDTO toDTO(SolveMessageInconsistenciesTask domainObject, String typeName) {
+        return new SolveMessageInconsistenciesTaskDTO(typeName);
+    }
+
+    public static TaskDTOModule<SolveMessageInconsistenciesTask, SolveMessageInconsistenciesTaskDTO> module(SolveMessageInconsistenciesService service) {
+        return DTOModule
+            .forDomainObject(SolveMessageInconsistenciesTask.class)
+            .convertToDTO(SolveMessageInconsistenciesTaskDTO.class)
+            .toDomainObjectConverter(dto -> dto.toDomainObject(service))
+            .toDTOConverter(SolveMessageInconsistenciesTaskDTO::toDTO)
+            .typeName(SOLVE_MESSAGE_INCONSISTENCIES.asString())
+            .withFactory(TaskDTOModule::new);
+    }
+
+    private final String type;
+
+    public SolveMessageInconsistenciesTaskDTO(@JsonProperty("type") String type) {
+        this.type = type;
+    }
+
+    private SolveMessageInconsistenciesTask toDomainObject(SolveMessageInconsistenciesService service) {
+        return new SolveMessageInconsistenciesTask(service);
+    }
+
+    @Override
+    public String getType() {
+        return type;
+    }
+}
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTaskSerializationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTaskSerializationTest.java
new file mode 100644
index 0000000..f6ec69d
--- /dev/null
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesTaskSerializationTest.java
@@ -0,0 +1,78 @@
+/****************************************************************
+ * 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.cassandra.mail.task;
+
+import static org.mockito.Mockito.mock;
+
+import java.time.Instant;
+
+import org.apache.james.JsonSerializationVerifier;
+import org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesTask.Details;
+import org.apache.james.util.ClassLoaderUtils;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class SolveMessageInconsistenciesTaskSerializationTest {
+
+    private static final SolveMessageInconsistenciesService SERVICE = mock(SolveMessageInconsistenciesService.class);
+    private static final SolveMessageInconsistenciesTask TASK = new SolveMessageInconsistenciesTask(SERVICE);
+
+    private static final Instant INSTANT = Instant.parse("2007-12-03T10:15:30.00Z");
+    private static final String MAILBOX_ID = "551f0580-82fb-11ea-970e-f9c83d4cf8c2";
+    private static final String MESSAGE_ID_1 = "d2bee791-7e63-11ea-883c-95b84008f979";
+    private static final String MESSAGE_ID_2 = "d2bee792-7e63-11ea-883c-95b84008f979";
+    private static final String MESSAGE_ID_3 = "ffffffff-7e63-11ea-883c-95b84008f979";
+    private static final Long MESSAGE_UID_1 = 1L;
+    private static final Long MESSAGE_UID_2 = 2L;
+    private static final Long MESSAGE_UID_3 = 3L;
+
+    private static final MessageInconsistenciesEntry MESSAGE_1 = MessageInconsistenciesEntry.builder()
+        .mailboxId(MAILBOX_ID)
+        .messageId(MESSAGE_ID_1)
+        .messageUid(MESSAGE_UID_1);
+    private static final MessageInconsistenciesEntry MESSAGE_2 = MessageInconsistenciesEntry.builder()
+        .mailboxId(MAILBOX_ID)
+        .messageId(MESSAGE_ID_2)
+        .messageUid(MESSAGE_UID_2);
+    private static final MessageInconsistenciesEntry MESSAGE_3 = MessageInconsistenciesEntry.builder()
+        .mailboxId(MAILBOX_ID)
+        .messageId(MESSAGE_ID_3)
+        .messageUid(MESSAGE_UID_3);
+
+    private static final Details DETAILS = new SolveMessageInconsistenciesTask.Details(INSTANT, 2, 1, 1, 0, 1, ImmutableList.of(MESSAGE_1, MESSAGE_2), ImmutableList.of(MESSAGE_3));
+
+    @Test
+    void taskShouldBeSerializable() throws Exception {
+        JsonSerializationVerifier.dtoModule(SolveMessageInconsistenciesTaskDTO.module(SERVICE))
+            .bean(TASK)
+            .json(ClassLoaderUtils.getSystemResourceAsString("json/solveMessageInconsistencies.task.json"))
+            .verify();
+    }
+
+    @Test
+    void additionalInformationShouldBeSerializable() throws Exception {
+        JsonSerializationVerifier.dtoModule(SolveMessageInconsistenciesTaskAdditionalInformationDTO.MODULE)
+            .bean(DETAILS)
+            .json(ClassLoaderUtils.getSystemResourceAsString("json/solveMessageInconsistencies.additionalInformation.json"))
+            .verify();
+    }
+
+}
diff --git a/mailbox/cassandra/src/test/resources/json/solveMessageInconsistencies.additionalInformation.json b/mailbox/cassandra/src/test/resources/json/solveMessageInconsistencies.additionalInformation.json
new file mode 100644
index 0000000..5ab72a0
--- /dev/null
+++ b/mailbox/cassandra/src/test/resources/json/solveMessageInconsistencies.additionalInformation.json
@@ -0,0 +1,28 @@
+{
+  "type":"solve-message-inconsistencies",
+  "timestamp":"2007-12-03T10:15:30Z",
+  "processedImapUidEntries": 2,
+  "processedMessageIdEntries": 1,
+  "addedMessageIdEntries": 1,
+  "updatedMessageIdEntries": 0,
+  "removedMessageIdEntries": 1,
+  "fixedInconsistencies": [
+    {
+      "mailboxId": "551f0580-82fb-11ea-970e-f9c83d4cf8c2",
+      "messageId": "d2bee791-7e63-11ea-883c-95b84008f979",
+      "uid": 1
+    },
+    {
+      "mailboxId": "551f0580-82fb-11ea-970e-f9c83d4cf8c2",
+      "messageId": "d2bee792-7e63-11ea-883c-95b84008f979",
+      "uid": 2
+    }
+  ],
+  "errors": [
+    {
+      "mailboxId": "551f0580-82fb-11ea-970e-f9c83d4cf8c2",
+      "messageId": "ffffffff-7e63-11ea-883c-95b84008f979",
+      "uid": 3
+    }
+  ]
+}
\ No newline at end of file
diff --git a/mailbox/cassandra/src/test/resources/json/solveMessageInconsistencies.task.json b/mailbox/cassandra/src/test/resources/json/solveMessageInconsistencies.task.json
new file mode 100644
index 0000000..f1c66ee
--- /dev/null
+++ b/mailbox/cassandra/src/test/resources/json/solveMessageInconsistencies.task.json
@@ -0,0 +1,3 @@
+{
+  "type":"solve-message-inconsistencies"
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin/webadmin-cassandra/src/main/java/org/apache/james/webadmin/routes/SolveMessageInconsistenciesRequestToTask.java b/server/protocols/webadmin/webadmin-cassandra/src/main/java/org/apache/james/webadmin/routes/SolveMessageInconsistenciesRequestToTask.java
new file mode 100644
index 0000000..8702b86
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-cassandra/src/main/java/org/apache/james/webadmin/routes/SolveMessageInconsistenciesRequestToTask.java
@@ -0,0 +1,36 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import javax.inject.Inject;
+
+import org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesService;
+import org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesTask;
+import org.apache.james.webadmin.tasks.TaskFromRequestRegistry;
+import org.apache.james.webadmin.tasks.TaskRegistrationKey;
+
+public class SolveMessageInconsistenciesRequestToTask extends TaskFromRequestRegistry.TaskRegistration {
+    private static final TaskRegistrationKey REGISTRATION_KEY = TaskRegistrationKey.of("SolveInconsistencies");
+
+    @Inject
+    public SolveMessageInconsistenciesRequestToTask(SolveMessageInconsistenciesService service) {
+        super(REGISTRATION_KEY, request -> new SolveMessageInconsistenciesTask(service));
+    }
+}


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