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