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/05/29 03:03:10 UTC
[james-project] 03/08: JAMES-3184 Exposes RunningOptions parameter
to WebAdmin routes
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 5d7edbee39e3053de8eaadad626beada5c58dbdd
Author: LanKhuat <kh...@gmail.com>
AuthorDate: Tue May 19 15:09:21 2020 +0700
JAMES-3184 Exposes RunningOptions parameter to WebAdmin routes
---
.../task/SolveMessageInconsistenciesService.java | 4 +-
...essageInconsistenciesTaskSerializationTest.java | 1 -
.../RabbitMQWebAdminServerIntegrationTest.java | 1 +
...equestToTask.java => RunningOptionsParser.java} | 29 ++-
.../SolveMessageInconsistenciesRequestToTask.java | 9 +-
...lveMessageInconsistenciesRequestToTaskTest.java | 229 +++++++++++++++++++++
6 files changed, 257 insertions(+), 16 deletions(-)
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesService.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesService.java
index 6106458..4f3b0b5 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesService.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/task/SolveMessageInconsistenciesService.java
@@ -182,7 +182,7 @@ public class SolveMessageInconsistenciesService {
}
}
- static class Context {
+ public static class Context {
static class Snapshot {
public static Builder builder() {
return new Builder();
@@ -416,7 +416,7 @@ public class SolveMessageInconsistenciesService {
this.messageIdDAO = messageIdDAO;
}
- Mono<Task.Result> fixMessageInconsistencies(Context context, RunningOptions runningOptions) {
+ public Mono<Task.Result> fixMessageInconsistencies(Context context, RunningOptions runningOptions) {
return Flux.concat(
fixInconsistenciesInMessageId(context, runningOptions),
fixInconsistenciesInImapUid(context, runningOptions))
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
index 3edb7ee..0d7717a 100644
--- 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
@@ -37,7 +37,6 @@ public class SolveMessageInconsistenciesTaskSerializationTest {
private static final SolveMessageInconsistenciesService SERVICE = mock(SolveMessageInconsistenciesService.class);
private static final SolveMessageInconsistenciesTask TASK = new SolveMessageInconsistenciesTask(SERVICE, new RunningOptions(2));
- private static final SolveMessageInconsistenciesTask LEGACY_TASK = new SolveMessageInconsistenciesTask(SERVICE, RunningOptions.DEFAULT);
private static final Instant INSTANT = Instant.parse("2007-12-03T10:15:30.00Z");
private static final String MAILBOX_ID = "551f0580-82fb-11ea-970e-f9c83d4cf8c2";
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java
index 0a1f4c8..44cb8dc 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerIntegrationTest.java
@@ -232,6 +232,7 @@ class RabbitMQWebAdminServerIntegrationTest extends WebAdminServerIntegrationTes
.body("additionalInformation.addedMessageIdEntries", is(0))
.body("additionalInformation.updatedMessageIdEntries", is(0))
.body("additionalInformation.removedMessageIdEntries", is(0))
+ .body("additionalInformation.runningOptions.messagesPerSecond", is(100))
.body("additionalInformation.fixedInconsistencies", hasSize(0))
.body("additionalInformation.errors", hasSize(0));
}
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/RunningOptionsParser.java
similarity index 63%
copy from server/protocols/webadmin/webadmin-cassandra/src/main/java/org/apache/james/webadmin/routes/SolveMessageInconsistenciesRequestToTask.java
copy to server/protocols/webadmin/webadmin-cassandra/src/main/java/org/apache/james/webadmin/routes/RunningOptionsParser.java
index 72e777a..9d68922 100644
--- 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/RunningOptionsParser.java
@@ -19,19 +19,26 @@
package org.apache.james.webadmin.routes;
-import javax.inject.Inject;
+import java.util.Optional;
-import org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesService;
import org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesService.RunningOptions;
-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");
+import spark.Request;
- @Inject
- public SolveMessageInconsistenciesRequestToTask(SolveMessageInconsistenciesService service) {
- super(REGISTRATION_KEY, request -> new SolveMessageInconsistenciesTask(service, RunningOptions.DEFAULT));
+public class RunningOptionsParser {
+ public static RunningOptions parse(Request request) {
+ return intQueryParameter(request, "messagesPerSecond")
+ .map(RunningOptions::new)
+ .orElse(RunningOptions.DEFAULT);
}
-}
+
+ public static Optional<Integer> intQueryParameter(Request request, String queryParameter) {
+ try {
+ return Optional.ofNullable(request.queryParams(queryParameter))
+ .map(Integer::parseInt);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(String.format("Illegal value supplied for query parameter '%s', expecting a " +
+ "strictly positive optional integer", queryParameter), e);
+ }
+ }
+}
\ 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
index 72e777a..30ab9a8 100644
--- 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
@@ -22,16 +22,21 @@ 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.SolveMessageInconsistenciesService.RunningOptions;
import org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesTask;
import org.apache.james.webadmin.tasks.TaskFromRequestRegistry;
import org.apache.james.webadmin.tasks.TaskRegistrationKey;
+import spark.Request;
+
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, RunningOptions.DEFAULT));
+ super(REGISTRATION_KEY, request -> toTask(request, service));
+ }
+
+ private static SolveMessageInconsistenciesTask toTask(Request request, SolveMessageInconsistenciesService service) {
+ return new SolveMessageInconsistenciesTask(service, RunningOptionsParser.parse(request));
}
}
diff --git a/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/routes/SolveMessageInconsistenciesRequestToTaskTest.java b/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/routes/SolveMessageInconsistenciesRequestToTaskTest.java
new file mode 100644
index 0000000..01cb39d
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/routes/SolveMessageInconsistenciesRequestToTaskTest.java
@@ -0,0 +1,229 @@
+/****************************************************************
+ * 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 static io.restassured.RestAssured.given;
+import static io.restassured.RestAssured.when;
+import static io.restassured.RestAssured.with;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+
+import org.apache.james.mailbox.cassandra.mail.task.SolveMessageInconsistenciesService;
+import org.apache.james.task.Hostname;
+import org.apache.james.task.MemoryTaskManager;
+import org.apache.james.task.Task;
+import org.apache.james.task.TaskManager;
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.WebAdminServer;
+import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.tasks.TaskFromRequestRegistry;
+import org.apache.james.webadmin.utils.ErrorResponder;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import io.restassured.RestAssured;
+import io.restassured.filter.log.LogDetail;
+import reactor.core.publisher.Mono;
+import spark.Service;
+
+public class SolveMessageInconsistenciesRequestToTaskTest {
+ private final class JMAPRoutes implements Routes {
+ private final SolveMessageInconsistenciesService service;
+ private final TaskManager taskManager;
+
+ private JMAPRoutes(SolveMessageInconsistenciesService service, TaskManager taskManager) {
+ this.service = service;
+ this.taskManager = taskManager;
+ }
+
+ @Override
+ public String getBasePath() {
+ return BASE_PATH;
+ }
+
+ @Override
+ public void define(Service service) {
+ service.post(BASE_PATH,
+ TaskFromRequestRegistry.builder()
+ .registrations(new SolveMessageInconsistenciesRequestToTask(this.service))
+ .buildAsRoute(taskManager),
+ new JsonTransformer());
+ }
+ }
+
+ static final String BASE_PATH = "/messages";
+
+ private WebAdminServer webAdminServer;
+ private SolveMessageInconsistenciesService service;
+ private MemoryTaskManager taskManager;
+
+ @BeforeEach
+ void setUp() {
+ JsonTransformer jsonTransformer = new JsonTransformer();
+ taskManager = new MemoryTaskManager(new Hostname("foo"));
+
+ service = mock(SolveMessageInconsistenciesService.class);
+ Mockito.when(service.fixMessageInconsistencies(any(), any())).thenReturn(Mono.just(Task.Result.COMPLETED));
+
+ webAdminServer = WebAdminUtils.createWebAdminServer(
+ new TasksRoutes(taskManager, jsonTransformer),
+ new JMAPRoutes(
+ service,
+ taskManager))
+ .start();
+
+ RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer)
+ .setBasePath(BASE_PATH)
+ .log(LogDetail.URI)
+ .build();
+ }
+
+ @AfterEach
+ void afterEach() {
+ webAdminServer.destroy();
+ taskManager.stop();
+ }
+
+ @Test
+ void actionRequestParameterShouldBeCompulsory() {
+ when()
+ .post()
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .body("statusCode", is(400))
+ .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+ .body("message", is("Invalid arguments supplied in the user request"))
+ .body("details", is("'action' query parameter is compulsory. Supported values are [SolveInconsistencies]"));
+ }
+
+ @Test
+ void postShouldFailUponEmptyAction() {
+ given()
+ .queryParam("action", "")
+ .post()
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .body("statusCode", is(400))
+ .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+ .body("message", is("Invalid arguments supplied in the user request"))
+ .body("details", is("'action' query parameter cannot be empty or blank. Supported values are [SolveInconsistencies]"));
+ }
+
+ @Test
+ void postShouldFailUponInvalidAction() {
+ given()
+ .queryParam("action", "invalid")
+ .post()
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .body("statusCode", is(400))
+ .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+ .body("message", is("Invalid arguments supplied in the user request"))
+ .body("details", is("Invalid value supplied for query parameter 'action': invalid. Supported values are [SolveInconsistencies]"));
+ }
+
+ @Test
+ void postShouldFailWhenMessagesPerSecondIsNotAnInt() {
+ given()
+ .queryParam("action", "SolveInconsistencies")
+ .queryParam("messagesPerSecond", "abc")
+ .post()
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .body("statusCode", is(400))
+ .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+ .body("message", is("Invalid arguments supplied in the user request"))
+ .body("details", is("Illegal value supplied for query parameter 'messagesPerSecond', expecting a strictly positive optional integer"));
+ }
+
+ @Test
+ void postShouldFailWhenMessagesPerSecondIsNegative() {
+ given()
+ .queryParam("action", "SolveInconsistencies")
+ .queryParam("messagesPerSecond", "-1")
+ .post()
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .body("statusCode", is(400))
+ .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+ .body("message", is("Invalid arguments supplied in the user request"))
+ .body("details", is("'messagesPerSecond' must be strictly positive"));
+ }
+
+ @Test
+ void postShouldFailWhenMessagesPerSecondIsZero() {
+ given()
+ .queryParam("action", "SolveInconsistencies")
+ .queryParam("messagesPerSecond", "0")
+ .post()
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .body("statusCode", is(400))
+ .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+ .body("message", is("Invalid arguments supplied in the user request"))
+ .body("details", is("'messagesPerSecond' must be strictly positive"));
+ }
+
+ @Test
+ void postShouldCreateANewTask() {
+ given()
+ .queryParam("action", "SolveInconsistencies")
+ .post()
+ .then()
+ .statusCode(HttpStatus.CREATED_201)
+ .body("taskId", notNullValue());
+ }
+
+ @Test
+ void postShouldCreateANewTaskWhenConcurrencyParametersSpecified() {
+ given()
+ .queryParam("messagesPerSecond", "1")
+ .queryParam("action", "SolveInconsistencies")
+ .post()
+ .then()
+ .statusCode(HttpStatus.CREATED_201)
+ .body("taskId", notNullValue());
+ }
+
+ @Test
+ void runningOptionsShouldBePartOfTaskDetails() {
+ String taskId = with()
+ .queryParam("action", "SolveInconsistencies")
+ .queryParam("messagesPerSecond", "20")
+ .post()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await")
+ .then()
+ .body("taskId", is(taskId))
+ .body("type", is("solve-message-inconsistencies"))
+ .body("additionalInformation.runningOptions.messagesPerSecond", is(20));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org