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/28 02:11:14 UTC

[james-project] 06/08: JAMES-3184 Expose RecomputeCurrentQuotasTask RunningOptions over webadmin

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 a803f40081d78d56c8339d6669692fb40d2fdda4
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu May 21 15:26:01 2020 +0700

    JAMES-3184 Expose RecomputeCurrentQuotasTask RunningOptions over webadmin
---
 .../james/webadmin/routes/UserQuotaRoutes.java     |  20 ++-
 .../james/webadmin/routes/UserQuotaRoutesTest.java | 152 +++++++++++++++++++++
 .../routes/WebAdminQuotaSearchTestSystem.java      |  14 +-
 3 files changed, 183 insertions(+), 3 deletions(-)

diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java
index 4201768..b34e12b 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java
@@ -89,9 +89,27 @@ public class UserQuotaRoutes implements Routes {
     public static final String USER_QUOTAS_OPERATIONS_INJECTION_KEY = "userQuotasOperations";
 
     public static class RecomputeCurrentQuotasRequestToTask extends TaskFromRequestRegistry.TaskRegistration {
+        private static final String USERS_PER_SECOND = "usersPerSecond";
+
         @Inject
         public RecomputeCurrentQuotasRequestToTask(RecomputeCurrentQuotasService service) {
-            super(RECOMPUTE_CURRENT_QUOTAS, request -> new RecomputeCurrentQuotasTask(service, RunningOptions.DEFAULT));
+            super(RECOMPUTE_CURRENT_QUOTAS, request -> new RecomputeCurrentQuotasTask(service,parseRunningOptions(request)));
+        }
+
+        private static RunningOptions parseRunningOptions(Request request) {
+            return intQueryParameter(request)
+                .map(RunningOptions::withUsersPerSecond)
+                .orElse(RunningOptions.DEFAULT);
+        }
+
+        private static Optional<Integer> intQueryParameter(Request request) {
+            try {
+                return Optional.ofNullable(request.queryParams(USERS_PER_SECOND))
+                    .map(Integer::parseInt);
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException(String.format("Illegal value supplied for query parameter '%s', expecting a " +
+                    "strictly positive optional integer", USERS_PER_SECOND), e);
+            }
         }
     }
 
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java
index d656dcc..e5e1825 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java
@@ -28,6 +28,9 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.Matchers.contains;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
 
 import java.io.ByteArrayInputStream;
 import java.nio.charset.StandardCharsets;
@@ -51,6 +54,7 @@ import org.apache.james.mailbox.quota.MaxQuotaManager;
 import org.apache.james.mailbox.quota.UserQuotaRootResolver;
 import org.apache.james.quota.search.QuotaSearchTestSystem;
 import org.apache.james.user.api.UsersRepository;
+import org.apache.james.webadmin.utils.ErrorResponder;
 import org.assertj.core.api.SoftAssertions;
 import org.eclipse.jetty.http.HttpStatus;
 import org.junit.jupiter.api.BeforeEach;
@@ -1257,4 +1261,152 @@ class UserQuotaRoutesTest {
         }
 
     }
+
+    @Nested
+    @ExtendWith(ScanningQuotaSearchExtension.class)
+    class PostRecomputeQuotas {
+        @Test
+        void actionRequestParameterShouldBeCompulsory() {
+            when()
+                .post("/quota/users")
+            .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("'task' query parameter is compulsory. Supported values are [RecomputeCurrentQuotas]"));
+        }
+
+        @Test
+        void postShouldFailUponEmptyAction() {
+            given()
+                .queryParam("task", "")
+                .post("/quota/users")
+            .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("'task' query parameter cannot be empty or blank. Supported values are [RecomputeCurrentQuotas]"));
+        }
+
+        @Test
+        void postShouldFailUponInvalidAction() {
+            given()
+                .queryParam("task", "invalid")
+                .post("/quota/users")
+            .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 'task': invalid. Supported values are [RecomputeCurrentQuotas]"));
+        }
+
+        @Test
+        void postShouldFailWhenUsersPerSecondIsNotAnInt() {
+            given()
+                .queryParam("task", "RecomputeCurrentQuotas")
+                .queryParam("usersPerSecond", "abc")
+                .post("/quota/users")
+            .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 'usersPerSecond', expecting a strictly positive optional integer"));
+        }
+
+        @Test
+        void postShouldFailWhenUsersPerSecondIsNegative() {
+            given()
+                .queryParam("task", "RecomputeCurrentQuotas")
+                .queryParam("usersPerSecond", "-1")
+                .post("/quota/users")
+            .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("'usersPerSecond' needs to be strictly positive"));
+        }
+
+        @Test
+        void postShouldFailWhenUsersPerSecondIsZero() {
+            given()
+                .queryParam("task", "RecomputeCurrentQuotas")
+                .queryParam("usersPerSecond", "0")
+                .post("/quota/users")
+            .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("'usersPerSecond' needs to be strictly positive"));
+        }
+
+        @Test
+        void postShouldCreateANewTask() {
+            given()
+                .queryParam("task", "RecomputeCurrentQuotas")
+                .post("/quota/users")
+            .then()
+                .statusCode(HttpStatus.CREATED_201)
+                .body("taskId", notNullValue());
+        }
+
+        @Test
+        void postShouldCreateANewTaskWhenConcurrencyParametersAreSpecified() {
+            given()
+                .queryParam("task", "RecomputeCurrentQuotas")
+                .queryParam("usersPerSecond", "1")
+                .post("/quota/users")
+            .then()
+                .statusCode(HttpStatus.CREATED_201)
+                .body("taskId", notNullValue());
+        }
+
+        @Test
+        void recomputeAllShouldCompleteWhenNoUser() {
+            String taskId = with()
+                .queryParam("task", "RecomputeCurrentQuotas")
+                .post("/quota/users")
+                .jsonPath()
+                .get("taskId");
+
+            given()
+                .basePath(TasksRoutes.BASE)
+            .when()
+                .get(taskId + "/await")
+            .then()
+                .body("status", is("completed"))
+                .body("taskId", is(taskId))
+                .body("type", is("recompute-current-quotas"))
+                .body("additionalInformation.processedQuotaRoots", is(0))
+                .body("additionalInformation.failedQuotaRoots", hasSize(0))
+                .body("additionalInformation.runningOptions.usersPerSecond", is(1))
+                .body("startedDate", is(notNullValue()))
+                .body("submitDate", is(notNullValue()))
+                .body("completedDate", is(notNullValue()));
+        }
+
+        @Test
+        void runningOptionsShouldBePartOfTaskDetails() {
+            String taskId = with()
+                .queryParam("task", "RecomputeCurrentQuotas")
+                .queryParam("usersPerSecond", "20")
+                .post("/quota/users")
+                .jsonPath()
+                .get("taskId");
+
+            given()
+                .basePath(TasksRoutes.BASE)
+            .when()
+                .get(taskId + "/await")
+            .then()
+                .body("taskId", is(taskId))
+                .body("type", is("recompute-current-quotas"))
+                .body("additionalInformation.runningOptions.usersPerSecond", is(20));
+        }
+    }
 }
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/WebAdminQuotaSearchTestSystem.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/WebAdminQuotaSearchTestSystem.java
index 898d5d6..b315dbc 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/WebAdminQuotaSearchTestSystem.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/WebAdminQuotaSearchTestSystem.java
@@ -19,9 +19,15 @@
 
 package org.apache.james.webadmin.routes;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.james.mailbox.quota.task.RecomputeCurrentQuotasService;
 import org.apache.james.quota.search.QuotaSearchTestSystem;
 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.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
@@ -34,6 +40,7 @@ import org.apache.james.webadmin.utils.JsonTransformer;
 import com.google.common.collect.ImmutableSet;
 
 import io.restassured.specification.RequestSpecification;
+import reactor.core.publisher.Mono;
 
 public class WebAdminQuotaSearchTestSystem {
     private final QuotaSearchTestSystem quotaSearchTestSystem;
@@ -51,12 +58,15 @@ public class WebAdminQuotaSearchTestSystem {
         QuotaModule quotaModule = new QuotaModule();
         JsonTransformer jsonTransformer = new JsonTransformer(quotaModule);
         TaskManager taskManager = new MemoryTaskManager(new Hostname("foo"));
+        RecomputeCurrentQuotasService mock = mock(RecomputeCurrentQuotasService.class);
+        when(mock.recomputeCurrentQuotas(any(), any())).thenReturn(Mono.just(Task.Result.COMPLETED));
+        TasksRoutes tasksRoutes = new TasksRoutes(taskManager, new JsonTransformer());
         UserQuotaRoutes userQuotaRoutes = new UserQuotaRoutes(quotaSearchTestSystem.getUsersRepository(),
             userQuotaService,
             jsonTransformer,
             ImmutableSet.of(quotaModule),
             taskManager,
-            ImmutableSet.of());
+            ImmutableSet.of(new UserQuotaRoutes.RecomputeCurrentQuotasRequestToTask(mock)));
         DomainQuotaRoutes domainQuotaRoutes = new DomainQuotaRoutes(
             quotaSearchTestSystem.getDomainList(),
             new DomainQuotaService(quotaSearchTestSystem.getMaxQuotaManager()),
@@ -67,7 +77,7 @@ public class WebAdminQuotaSearchTestSystem {
             new GlobalQuotaService(quotaSearchTestSystem.getMaxQuotaManager()),
             jsonTransformer);
 
-        this.webAdminServer = WebAdminUtils.createWebAdminServer(userQuotaRoutes, domainQuotaRoutes, globalQuotaRoutes)
+        this.webAdminServer = WebAdminUtils.createWebAdminServer(userQuotaRoutes, domainQuotaRoutes, globalQuotaRoutes, tasksRoutes)
             .start();
 
         this.requestSpecBuilder = WebAdminUtils.buildRequestSpecification(webAdminServer)


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