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 2019/05/30 07:22:21 UTC
[james-project] 10/19: MAILBOX-351 WebAdmin route to allow me to
reIndex previous tasks failures
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 3b040cad230da8e3b4dbb260bfcdbed2a16992d2
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu May 23 18:10:15 2019 +0700
MAILBOX-351 WebAdmin route to allow me to reIndex previous tasks failures
---
.../org/apache/james/webadmin/dto/TaskIdDto.java | 2 +-
.../apache/james/webadmin/routes/TasksRoutes.java | 3 +-
.../apache/james/webadmin/dto/TaskIdDtoTest.java | 4 +-
.../james/webadmin/routes/TasksRoutesTest.java | 4 +-
.../james/webadmin/routes/ReindexingRoutes.java | 76 ++++++-
.../service/PreviousReIndexingService.java | 60 ++++++
.../webadmin/routes/ReindexingRoutesTest.java | 222 +++++++++++++++++++++
.../main/java/org/apache/james/task/TaskId.java | 17 +-
.../java/org/apache/james/task/TaskManager.java | 22 +-
9 files changed, 389 insertions(+), 21 deletions(-)
diff --git a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/dto/TaskIdDto.java b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/dto/TaskIdDto.java
index 35f88e9..fbb74f0 100644
--- a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/dto/TaskIdDto.java
+++ b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/dto/TaskIdDto.java
@@ -33,7 +33,7 @@ public class TaskIdDto {
public static TaskIdDto respond(Response response, TaskId taskId) {
response.status(HttpStatus.CREATED_201);
- response.header(LOCATION.asString(), TasksRoutes.BASE + "/" + taskId.getValue());
+ response.header(LOCATION.asString(), TasksRoutes.BASE + "/" + taskId.asString());
return TaskIdDto.from(taskId);
}
diff --git a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/routes/TasksRoutes.java b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/routes/TasksRoutes.java
index 7dd1204..84f6eff 100644
--- a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/routes/TasksRoutes.java
+++ b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/routes/TasksRoutes.java
@@ -21,7 +21,6 @@ package org.apache.james.webadmin.routes;
import java.util.List;
import java.util.Optional;
-import java.util.UUID;
import java.util.function.Supplier;
import javax.inject.Inject;
@@ -172,7 +171,7 @@ public class TasksRoutes implements Routes {
private TaskId getTaskId(Request req) {
try {
String id = req.params("id");
- return new TaskId(UUID.fromString(id));
+ return TaskId.fromString(id);
} catch (Exception e) {
throw ErrorResponder.builder()
.statusCode(HttpStatus.BAD_REQUEST_400)
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/dto/TaskIdDtoTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/dto/TaskIdDtoTest.java
index 5f85a54..3a593eb 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/dto/TaskIdDtoTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/dto/TaskIdDtoTest.java
@@ -24,8 +24,6 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
-import java.util.UUID;
-
import org.apache.james.task.TaskId;
import org.eclipse.jetty.http.HttpStatus;
import org.junit.Test;
@@ -38,7 +36,7 @@ public class TaskIdDtoTest {
@Test
public void respondShouldReturnCreatedWithTaskIdHeader() {
Response response = mock(Response.class);
- TaskId taskId = new TaskId(UUID.fromString(UID_VALUE));
+ TaskId taskId = TaskId.fromString(UID_VALUE);
TaskIdDto.respond(response, taskId);
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/TasksRoutesTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/TasksRoutesTest.java
index 39947c0..1642068 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/TasksRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/TasksRoutesTest.java
@@ -99,7 +99,7 @@ public class TasksRoutesTest {
.statusCode(HttpStatus.OK_200)
.body("", hasSize(1))
.body("[0].status", is(TaskManager.Status.IN_PROGRESS.getValue()))
- .body("[0].taskId", is(taskId.getValue().toString()))
+ .body("[0].taskId", is(taskId.asString()))
.body("[0].class", is(not(empty())));
}
@@ -130,7 +130,7 @@ public class TasksRoutesTest {
.statusCode(HttpStatus.OK_200)
.body("", hasSize(1))
.body("[0].status", is(TaskManager.Status.IN_PROGRESS.getValue()))
- .body("[0].taskId", is(taskId.getValue().toString()))
+ .body("[0].taskId", is(taskId.asString()))
.body("[0].type", is(Task.UNKNOWN));
}
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java
index 8c5a773..083579e 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/ReindexingRoutes.java
@@ -28,13 +28,16 @@ import org.apache.james.core.User;
import org.apache.james.mailbox.MessageUid;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.exception.MailboxNotFoundException;
+import org.apache.james.mailbox.indexer.IndexingDetailInformation;
import org.apache.james.mailbox.indexer.ReIndexer;
import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.task.Task;
import org.apache.james.task.TaskId;
import org.apache.james.task.TaskManager;
+import org.apache.james.task.TaskNotFoundException;
import org.apache.james.webadmin.Routes;
import org.apache.james.webadmin.dto.TaskIdDto;
+import org.apache.james.webadmin.service.PreviousReIndexingService;
import org.apache.james.webadmin.utils.ErrorResponder;
import org.apache.james.webadmin.utils.JsonTransformer;
import org.eclipse.jetty.http.HttpStatus;
@@ -62,19 +65,22 @@ public class ReindexingRoutes implements Routes {
private static final String BASE_PATH = "/mailboxes";
private static final String USER_QUERY_PARAM = "user";
+ private static final String RE_INDEX_FAILED_MESSAGES_QUERY_PARAM = "reIndexFailedMessagesOf";
private static final String MAILBOX_PARAM = ":mailbox";
private static final String UID_PARAM = ":uid";
private static final String MAILBOX_PATH = BASE_PATH + "/" + MAILBOX_PARAM;
private static final String MESSAGE_PATH = MAILBOX_PATH + "/mails/" + UID_PARAM;
private final TaskManager taskManager;
+ private final PreviousReIndexingService previousReIndexingService;
private final MailboxId.Factory mailboxIdFactory;
private final ReIndexer reIndexer;
private final JsonTransformer jsonTransformer;
@Inject
- ReindexingRoutes(TaskManager taskManager, MailboxId.Factory mailboxIdFactory, ReIndexer reIndexer, JsonTransformer jsonTransformer) {
+ ReindexingRoutes(TaskManager taskManager, PreviousReIndexingService previousReIndexingService, MailboxId.Factory mailboxIdFactory, ReIndexer reIndexer, JsonTransformer jsonTransformer) {
this.taskManager = taskManager;
+ this.previousReIndexingService = previousReIndexingService;
this.mailboxIdFactory = mailboxIdFactory;
this.reIndexer = reIndexer;
this.jsonTransformer = jsonTransformer;
@@ -110,7 +116,15 @@ public class ReindexingRoutes implements Routes {
dataType = "String",
defaultValue = "none",
example = "?user=toto%40domain.tld",
- value = "optional. If present, only mailboxes of that user will be reIndexed.")
+ value = "optional. If present, only mailboxes of that user will be reIndexed."),
+ @ApiImplicitParam(
+ name = "reIndexFailedMessagesOf",
+ paramType = "query parameter",
+ dataType = "String",
+ defaultValue = "none",
+ example = "?reIndexFailedMessagesOf=3294a976-ce63-491e-bd52-1b6f465ed7a2",
+ value = "optional. References a previously run reIndexing task. if present, the messages that this previous " +
+ "task failed to index will be reIndexed.")
})
@ApiResponses(value = {
@ApiResponse(code = HttpStatus.CREATED_201, message = "Task is created", response = TaskIdDto.class),
@@ -118,10 +132,62 @@ public class ReindexingRoutes implements Routes {
@ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - details in the returned error message")
})
private TaskIdDto reIndexAll(Request request, Response response) {
- if (Strings.isNullOrEmpty(request.queryParams(USER_QUERY_PARAM))) {
- return wrap(request, response, reIndexer::reIndex);
+ boolean userReIndexing = !Strings.isNullOrEmpty(request.queryParams(USER_QUERY_PARAM));
+ boolean indexingCorrection = !Strings.isNullOrEmpty(request.queryParams(RE_INDEX_FAILED_MESSAGES_QUERY_PARAM));
+ if (userReIndexing && indexingCorrection) {
+ return rejectInvalidQueryParameterCombination();
+ }
+ if (userReIndexing) {
+ return wrap(request, response, () -> reIndexer.reIndex(extractUser(request)));
+ }
+ if (indexingCorrection) {
+ IndexingDetailInformation indexingDetailInformation = retrieveIndexingExecutionDetails(request);
+ return wrap(request, response, () -> reIndexer.reIndex(indexingDetailInformation.failures()));
+ }
+ return wrap(request, response, reIndexer::reIndex);
+ }
+
+ private IndexingDetailInformation retrieveIndexingExecutionDetails(Request request) {
+ TaskId taskId = getTaskId(request);
+ try {
+ return previousReIndexingService.retrieveIndexingExecutionDetails(taskId);
+ } catch (PreviousReIndexingService.NotAnIndexingRetryiableTask | PreviousReIndexingService.TaskNotYetFinishedException e) {
+ throw ErrorResponder.builder()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+ .message("Invalid task id")
+ .cause(e)
+ .haltError();
+ } catch (TaskNotFoundException e) {
+ throw ErrorResponder.builder()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+ .message("TaskId " + taskId.asString() + " does not exist")
+ .cause(e)
+ .haltError();
+ }
+ }
+
+ private TaskId getTaskId(Request request) {
+ try {
+ String id = request.queryParams(RE_INDEX_FAILED_MESSAGES_QUERY_PARAM);
+ return TaskId.fromString(id);
+ } catch (Exception e) {
+ throw ErrorResponder.builder()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .cause(e)
+ .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+ .message("Invalid task id")
+ .haltError();
}
- return wrap(request, response, () -> reIndexer.reIndex(extractUser(request)));
+ }
+
+ private TaskIdDto rejectInvalidQueryParameterCombination() {
+ throw ErrorResponder.builder()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+ .message("Can not specify '" + USER_QUERY_PARAM + "' and '" + RE_INDEX_FAILED_MESSAGES_QUERY_PARAM + "' query parameters at the same time")
+ .haltError();
}
@POST
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/PreviousReIndexingService.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/PreviousReIndexingService.java
new file mode 100644
index 0000000..2df5879
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/PreviousReIndexingService.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.webadmin.service;
+
+import javax.inject.Inject;
+
+import org.apache.james.mailbox.indexer.IndexingDetailInformation;
+import org.apache.james.task.TaskExecutionDetails;
+import org.apache.james.task.TaskId;
+import org.apache.james.task.TaskManager;
+import org.apache.james.task.TaskNotFoundException;
+
+public class PreviousReIndexingService {
+ public static class TaskNotYetFinishedException extends RuntimeException {
+ TaskNotYetFinishedException(TaskManager.Status currentStatus) {
+ super("Task is not yet finished. Current status is: " + currentStatus);
+ }
+ }
+
+ public static class NotAnIndexingRetryiableTask extends RuntimeException {
+ NotAnIndexingRetryiableTask(String type) {
+ super("'" + type + "' is not a valid type of task for retrying a failed indexing");
+ }
+ }
+
+ private final TaskManager taskManager;
+
+ @Inject
+ public PreviousReIndexingService(TaskManager taskManager) {
+ this.taskManager = taskManager;
+ }
+
+ public IndexingDetailInformation retrieveIndexingExecutionDetails(TaskId taskId) throws NotAnIndexingRetryiableTask, TaskNotFoundException, TaskNotYetFinishedException {
+ TaskExecutionDetails executionDetails = taskManager.getExecutionDetails(taskId);
+ if (!executionDetails.getStatus().isFinished()) {
+ throw new TaskNotYetFinishedException(executionDetails.getStatus());
+ }
+ return executionDetails.getAdditionalInformation()
+ .filter(additionalInformation -> additionalInformation instanceof IndexingDetailInformation)
+ .map(additionalInformation -> (IndexingDetailInformation) additionalInformation)
+ .orElseThrow(() -> new NotAnIndexingRetryiableTask(executionDetails.getType()));
+ }
+}
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/ReindexingRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/ReindexingRoutesTest.java
index e0af217..091ddb9 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/ReindexingRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/ReindexingRoutesTest.java
@@ -27,7 +27,10 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -48,6 +51,7 @@ import org.apache.james.metrics.logger.DefaultMetricFactory;
import org.apache.james.task.MemoryTaskManager;
import org.apache.james.webadmin.WebAdminServer;
import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.service.PreviousReIndexingService;
import org.apache.james.webadmin.utils.ErrorResponder;
import org.apache.james.webadmin.utils.JsonTransformer;
import org.apache.mailbox.tools.indexer.FullReindexingTask;
@@ -94,6 +98,7 @@ class ReindexingRoutesTest {
new TasksRoutes(taskManager, jsonTransformer),
new ReindexingRoutes(
taskManager,
+ new PreviousReIndexingService(taskManager),
mailboxIdFactory,
reIndexer,
jsonTransformer),
@@ -828,4 +833,221 @@ class ReindexingRoutesTest {
}
}
}
+
+ @Nested
+ class FixingReIndexing {
+ @Nested
+ class Validation {
+ @Test
+ void fixingReIndexingShouldThrowOnMissingTaskQueryParameter() {
+ String taskId = with()
+ .post("/mailboxes?task=reIndex")
+ .jsonPath()
+ .get("taskId");
+
+ with()
+ .basePath(TasksRoutes.BASE)
+ .get(taskId + "/await");
+
+ given()
+ .queryParam("reIndexFailedMessagesOf", taskId)
+ .when()
+ .post("/mailboxes")
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .body("statusCode", is(400))
+ .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+ .body("message", is("task query parameter is mandatory. The only supported value is `reIndex`"));
+ }
+
+ @Test
+ void fixingReIndexingShouldThrowOnUserParameter() {
+ String taskId = with()
+ .post("/mailboxes?task=reIndex")
+ .jsonPath()
+ .get("taskId");
+
+ with()
+ .basePath(TasksRoutes.BASE)
+ .get(taskId + "/await");
+
+ given()
+ .queryParam("reIndexFailedMessagesOf", taskId)
+ .queryParam("task", "reIndex")
+ .queryParam("user", "bob@domain.tld")
+ .when()
+ .post("/mailboxes")
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .body("statusCode", is(400))
+ .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+ .body("message", is("Can not specify 'user' and 'reIndexFailedMessagesOf' query parameters at the same time"));
+ }
+
+ @Test
+ void fixingReIndexingShouldFailWithBadTask() {
+ String taskId = with()
+ .post("/mailboxes?task=reIndex")
+ .jsonPath()
+ .get("taskId");
+
+ with()
+ .basePath(TasksRoutes.BASE)
+ .get(taskId + "/await");
+
+ given()
+ .queryParam("reIndexFailedMessagesOf", taskId)
+ .when()
+ .post("/mailboxes?task=bad")
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .body("statusCode", is(400))
+ .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+ .body("message", is("task query parameter is mandatory. The only supported value is `reIndex`"));
+ }
+
+ @Test
+ void fixingReIndexingShouldRejectNotExistingTask() {
+ String taskId = "bbdb69c9-082a-44b0-a85a-6e33e74287a5";
+
+ given()
+ .queryParam("reIndexFailedMessagesOf", taskId)
+ .when()
+ .post("/mailboxes?task=bad")
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .body("statusCode", is(400))
+ .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+ .body("message", is("TaskId bbdb69c9-082a-44b0-a85a-6e33e74287a5 does not exist"));
+ }
+ }
+
+ @Nested
+ class TaskDetails {
+ @Test
+ void fixingReIndexingShouldNotFailWhenNoMail() {
+ String taskId = with()
+ .post("/mailboxes?task=reIndex")
+ .jsonPath()
+ .get("taskId");
+
+ with()
+ .basePath(TasksRoutes.BASE)
+ .get(taskId + "/await");
+
+ String fixingTaskId = with()
+ .queryParam("reIndexFailedMessagesOf", taskId)
+ .queryParam("task", "reIndex")
+ .post("/mailboxes")
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(fixingTaskId + "/await")
+ .then()
+ .body("status", is("completed"))
+ .body("taskId", is(notNullValue()))
+ .body("type", is("ReIndexPreviousFailures"))
+ .body("additionalInformation.successfullyReprocessMailCount", is(0))
+ .body("additionalInformation.failedReprocessedMailCount", is(0))
+ .body("startedDate", is(notNullValue()))
+ .body("submitDate", is(notNullValue()))
+ .body("completedDate", is(notNullValue()));
+ }
+
+ @Test
+ void fixingReIndexingShouldReturnTaskDetailsWhenMail() throws Exception {
+ MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+ mailboxManager.createMailbox(INBOX, systemSession).get();
+ mailboxManager.getMailbox(INBOX, systemSession)
+ .appendMessage(
+ MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
+ systemSession);
+
+ doThrow(new RuntimeException()).when(searchIndex).add(any(MailboxSession.class), any(Mailbox.class), any(MailboxMessage.class));
+
+ String taskId = with()
+ .post("/mailboxes?task=reIndex")
+ .jsonPath()
+ .get("taskId");
+
+ with()
+ .basePath(TasksRoutes.BASE)
+ .get(taskId + "/await");
+
+ doNothing().when(searchIndex).add(any(MailboxSession.class), any(Mailbox.class), any(MailboxMessage.class));
+
+ String fixingTaskId = with()
+ .queryParam("reIndexFailedMessagesOf", taskId)
+ .queryParam("task", "reIndex")
+ .post("/mailboxes")
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(fixingTaskId + "/await")
+ .then()
+ .body("status", is("completed"))
+ .body("taskId", is(notNullValue()))
+ .body("type", is("ReIndexPreviousFailures"))
+ .body("additionalInformation.successfullyReprocessMailCount", is(1))
+ .body("additionalInformation.failedReprocessedMailCount", is(0))
+ .body("startedDate", is(notNullValue()))
+ .body("submitDate", is(notNullValue()))
+ .body("completedDate", is(notNullValue()));
+ }
+ }
+
+ @Nested
+ class SideEffects {
+ @Test
+ void fixingReprocessingShouldPerformReprocessingWhenMail() throws Exception {
+ MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+ MailboxId mailboxId = mailboxManager.createMailbox(INBOX, systemSession).get();
+ ComposedMessageId createdMessage = mailboxManager.getMailbox(INBOX, systemSession)
+ .appendMessage(
+ MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
+ systemSession);
+
+ doThrow(new RuntimeException()).when(searchIndex).add(any(MailboxSession.class), any(Mailbox.class), any(MailboxMessage.class));
+
+ String taskId = with()
+ .post("/mailboxes?task=reIndex")
+ .jsonPath()
+ .get("taskId");
+
+ with()
+ .basePath(TasksRoutes.BASE)
+ .get(taskId + "/await");
+
+ reset(searchIndex);
+
+ String fixingTaskId = with()
+ .queryParam("reIndexFailedMessagesOf", taskId)
+ .queryParam("task", "reIndex")
+ .post("/mailboxes")
+ .jsonPath()
+ .get("taskId");
+
+ with()
+ .basePath(TasksRoutes.BASE)
+ .get(fixingTaskId + "/await")
+ .then()
+ .body("status", is("completed"));
+
+ ArgumentCaptor<MailboxMessage> messageCaptor = ArgumentCaptor.forClass(MailboxMessage.class);
+ ArgumentCaptor<Mailbox> mailboxCaptor = ArgumentCaptor.forClass(Mailbox.class);
+ verify(searchIndex).add(any(MailboxSession.class), mailboxCaptor.capture(), messageCaptor.capture());
+ verifyNoMoreInteractions(searchIndex);
+
+ assertThat(mailboxCaptor.getValue()).matches(mailbox -> mailbox.getMailboxId().equals(mailboxId));
+ assertThat(messageCaptor.getValue()).matches(message -> message.getMailboxId().equals(mailboxId)
+ && message.getUid().equals(createdMessage.getUid()));
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/server/task/src/main/java/org/apache/james/task/TaskId.java b/server/task/src/main/java/org/apache/james/task/TaskId.java
index 4b66feb..3f30712 100644
--- a/server/task/src/main/java/org/apache/james/task/TaskId.java
+++ b/server/task/src/main/java/org/apache/james/task/TaskId.java
@@ -23,11 +23,22 @@ import java.util.Objects;
import java.util.UUID;
import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
public class TaskId {
public static TaskId generateTaskId() {
- return new TaskId(UUID.randomUUID());
+ return fromUUID(UUID.randomUUID());
+ }
+
+ public static TaskId fromUUID(UUID uuid) {
+ Preconditions.checkNotNull(uuid, "'uuid' should not be null");
+ return new TaskId(uuid);
+ }
+
+ public static TaskId fromString(String uuid) {
+ Preconditions.checkNotNull(uuid, "'uuid' should not be null");
+ return fromUUID(UUID.fromString(uuid));
}
private final UUID value;
@@ -40,6 +51,10 @@ public class TaskId {
return value;
}
+ public String asString() {
+ return value.toString();
+ }
+
@Override
public final boolean equals(Object o) {
if (o instanceof TaskId) {
diff --git a/server/task/src/main/java/org/apache/james/task/TaskManager.java b/server/task/src/main/java/org/apache/james/task/TaskManager.java
index de3e16b..b04f2c2 100644
--- a/server/task/src/main/java/org/apache/james/task/TaskManager.java
+++ b/server/task/src/main/java/org/apache/james/task/TaskManager.java
@@ -23,13 +23,15 @@ import java.util.Arrays;
import java.util.List;
public interface TaskManager {
+ boolean FINISHED = true;
+
enum Status {
- WAITING("waiting"),
- IN_PROGRESS("inProgress"),
- COMPLETED("completed"),
- CANCEL_REQUESTED("canceledRequested"),
- CANCELLED("canceled"),
- FAILED("failed");
+ WAITING("waiting", !FINISHED),
+ IN_PROGRESS("inProgress", !FINISHED),
+ CANCEL_REQUESTED("canceledRequested", !FINISHED),
+ COMPLETED("completed", FINISHED),
+ CANCELLED("canceled", FINISHED),
+ FAILED("failed", FINISHED);
public static Status fromString(String value) {
return Arrays.stream(values())
@@ -40,14 +42,20 @@ public interface TaskManager {
}
private final String value;
+ private final boolean finished;
- Status(String value) {
+ Status(String value, boolean finished) {
this.value = value;
+ this.finished = finished;
}
public String getValue() {
return value;
}
+
+ public boolean isFinished() {
+ return finished;
+ }
}
TaskId submit(Task task);
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org