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 <[email protected]> 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: [email protected] For additional commands, e-mail: [email protected]
