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/04/29 01:14:45 UTC

[james-project] 11/27: JAMES-3138 Task for recomputing current quotas

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 ab4e4e3b1df2b4be221dfd233990582b0801a606
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Mon Apr 13 17:12:02 2020 +0700

    JAMES-3138 Task for recomputing current quotas
---
 .../org/apache/james/mailbox/model/QuotaRoot.java  |   5 +
 mailbox/tools/quota-recompute/pom.xml              |  20 ++++
 .../quota/task/RecomputeCurrentQuotasTask.java     | 101 +++++++++++++++++++++
 ...eCurrentQuotasTaskAdditionalInformationDTO.java |  87 ++++++++++++++++++
 .../quota/task/RecomputeCurrentQuotasTaskDTO.java  |  57 ++++++++++++
 ...ecomputeCurrentQuotasTaskSerializationTest.java |  61 +++++++++++++
 6 files changed, 331 insertions(+)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
index c7a825a..1ad8d20 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
@@ -73,4 +73,9 @@ public class QuotaRoot {
                 .add("domain", domain)
                 .toString();
     }
+
+    public String asString() {
+        return domain.map(domainValue -> value + "@" + domainValue.asString())
+            .orElse(value);
+    }
 }
diff --git a/mailbox/tools/quota-recompute/pom.xml b/mailbox/tools/quota-recompute/pom.xml
index 34c21a7..2c59165 100644
--- a/mailbox/tools/quota-recompute/pom.xml
+++ b/mailbox/tools/quota-recompute/pom.xml
@@ -38,13 +38,33 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>james-json</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-server-data-api</artifactId>
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-task-json</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>net.javacrumbs.json-unit</groupId>
+            <artifactId>json-unit-assertj</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/mailbox/tools/quota-recompute/src/main/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTask.java b/mailbox/tools/quota-recompute/src/main/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTask.java
new file mode 100644
index 0000000..050737b
--- /dev/null
+++ b/mailbox/tools/quota-recompute/src/main/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTask.java
@@ -0,0 +1,101 @@
+/****************************************************************
+ * 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.mailbox.quota.task;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.util.Optional;
+
+import org.apache.james.mailbox.model.QuotaRoot;
+import org.apache.james.mailbox.quota.task.RecomputeCurrentQuotasService.Context;
+import org.apache.james.mailbox.quota.task.RecomputeCurrentQuotasService.Context.Snapshot;
+import org.apache.james.task.Task;
+import org.apache.james.task.TaskExecutionDetails;
+import org.apache.james.task.TaskType;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableList;
+
+import reactor.core.scheduler.Schedulers;
+
+public class RecomputeCurrentQuotasTask implements Task {
+    static final TaskType RECOMPUTE_CURRENT_QUOTAS = TaskType.of("recompute-current-quotas");
+
+    public static class Details implements TaskExecutionDetails.AdditionalInformation {
+        private final Instant instant;
+        private final long processedQuotaRoots;
+        private final ImmutableList<String> failedQuotaRoots;
+
+        Details(Instant instant, long processedQuotaRoots, ImmutableList<String> failedQuotaRoots) {
+            this.instant = instant;
+            this.processedQuotaRoots = processedQuotaRoots;
+            this.failedQuotaRoots = failedQuotaRoots;
+        }
+
+        @Override
+        public Instant timestamp() {
+            return instant;
+        }
+
+        @JsonProperty("processedQuotaRoots")
+        long getProcessedQuotaRoots() {
+            return processedQuotaRoots;
+        }
+
+        @JsonProperty("failedQuotaRoots")
+        ImmutableList<String> getFailedQuotaRoots() {
+            return failedQuotaRoots;
+        }
+    }
+
+    private final RecomputeCurrentQuotasService service;
+
+    private Context context;
+
+    public RecomputeCurrentQuotasTask(RecomputeCurrentQuotasService service) {
+        this.service = service;
+        this.context = new Context();
+    }
+
+    @Override
+    public Task.Result run() {
+        return service.recomputeCurrentQuotas(context)
+            .subscribeOn(Schedulers.elastic())
+            .block();
+    }
+
+    @Override
+    public TaskType type() {
+        return RECOMPUTE_CURRENT_QUOTAS;
+    }
+
+    @Override
+    public Optional<TaskExecutionDetails.AdditionalInformation> details() {
+        Snapshot snapshot = context.snapshot();
+
+        return Optional.of(new Details(Clock.systemUTC().instant(),
+            snapshot.getProcessedQuotaRootCount(),
+            snapshot.getFailedQuotaRoots()
+                .stream()
+                .map(QuotaRoot::asString)
+                .collect(Guavate.toImmutableList())));
+    }
+}
diff --git a/mailbox/tools/quota-recompute/src/main/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTaskAdditionalInformationDTO.java b/mailbox/tools/quota-recompute/src/main/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTaskAdditionalInformationDTO.java
new file mode 100644
index 0000000..5bebcee
--- /dev/null
+++ b/mailbox/tools/quota-recompute/src/main/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTaskAdditionalInformationDTO.java
@@ -0,0 +1,87 @@
+/****************************************************************
+ * 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.mailbox.quota.task;
+
+import java.time.Instant;
+
+import org.apache.james.json.DTOModule;
+import org.apache.james.server.task.json.dto.AdditionalInformationDTO;
+import org.apache.james.server.task.json.dto.AdditionalInformationDTOModule;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.ImmutableList;
+
+public class RecomputeCurrentQuotasTaskAdditionalInformationDTO implements AdditionalInformationDTO {
+    private static RecomputeCurrentQuotasTaskAdditionalInformationDTO fromDomainObject(RecomputeCurrentQuotasTask.Details details, String type) {
+        return new RecomputeCurrentQuotasTaskAdditionalInformationDTO(
+            type,
+            details.getProcessedQuotaRoots(),
+            details.getFailedQuotaRoots(),
+            details.timestamp());
+    }
+
+    public static final AdditionalInformationDTOModule<RecomputeCurrentQuotasTask.Details, RecomputeCurrentQuotasTaskAdditionalInformationDTO> MODULE =
+        DTOModule
+            .forDomainObject(RecomputeCurrentQuotasTask.Details.class)
+            .convertToDTO(RecomputeCurrentQuotasTaskAdditionalInformationDTO.class)
+            .toDomainObjectConverter(RecomputeCurrentQuotasTaskAdditionalInformationDTO::toDomainObject)
+            .toDTOConverter(RecomputeCurrentQuotasTaskAdditionalInformationDTO::fromDomainObject)
+            .typeName(RecomputeCurrentQuotasTask.RECOMPUTE_CURRENT_QUOTAS.asString())
+            .withFactory(AdditionalInformationDTOModule::new);
+
+    private final String type;
+    private final long processedQuotaRoots;
+    private final ImmutableList<String> failedQuotaRoots;
+    private final Instant timestamp;
+
+    public RecomputeCurrentQuotasTaskAdditionalInformationDTO(@JsonProperty("type") String type,
+                                                              @JsonProperty("processedQuotaRoots") long processedQuotaRoots,
+                                                              @JsonProperty("failedQuotaRoots") ImmutableList<String> failedQuotaRoots,
+                                                              @JsonProperty("timestamp") Instant timestamp) {
+        this.type = type;
+        this.processedQuotaRoots = processedQuotaRoots;
+        this.failedQuotaRoots = failedQuotaRoots;
+        this.timestamp = timestamp;
+    }
+
+    public long getProcessedQuotaRoots() {
+        return processedQuotaRoots;
+    }
+
+    public ImmutableList<String> getFailedQuotaRoots() {
+        return failedQuotaRoots;
+    }
+
+    @Override
+    public Instant getTimestamp() {
+        return timestamp;
+    }
+
+    @Override
+    public String getType() {
+        return type;
+    }
+
+    private RecomputeCurrentQuotasTask.Details toDomainObject() {
+        return new RecomputeCurrentQuotasTask.Details(timestamp,
+            processedQuotaRoots,
+            failedQuotaRoots);
+    }
+}
diff --git a/mailbox/tools/quota-recompute/src/main/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTaskDTO.java b/mailbox/tools/quota-recompute/src/main/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTaskDTO.java
new file mode 100644
index 0000000..33d5a4e
--- /dev/null
+++ b/mailbox/tools/quota-recompute/src/main/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTaskDTO.java
@@ -0,0 +1,57 @@
+/****************************************************************
+ * 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.mailbox.quota.task;
+
+import org.apache.james.json.DTOModule;
+import org.apache.james.server.task.json.dto.TaskDTO;
+import org.apache.james.server.task.json.dto.TaskDTOModule;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class RecomputeCurrentQuotasTaskDTO implements TaskDTO {
+    private static RecomputeCurrentQuotasTaskDTO toDTO(RecomputeCurrentQuotasTask domainObject, String typeName) {
+        return new RecomputeCurrentQuotasTaskDTO(typeName);
+    }
+
+    public static TaskDTOModule<RecomputeCurrentQuotasTask, RecomputeCurrentQuotasTaskDTO> module(RecomputeCurrentQuotasService service) {
+        return DTOModule
+            .forDomainObject(RecomputeCurrentQuotasTask.class)
+            .convertToDTO(RecomputeCurrentQuotasTaskDTO.class)
+            .toDomainObjectConverter(dto -> dto.toDomainObject(service))
+            .toDTOConverter(RecomputeCurrentQuotasTaskDTO::toDTO)
+            .typeName(RecomputeCurrentQuotasTask.RECOMPUTE_CURRENT_QUOTAS.asString())
+            .withFactory(TaskDTOModule::new);
+    }
+
+    private final String type;
+
+    public RecomputeCurrentQuotasTaskDTO(@JsonProperty("type") String type) {
+        this.type = type;
+    }
+
+    private RecomputeCurrentQuotasTask toDomainObject(RecomputeCurrentQuotasService service) {
+        return new RecomputeCurrentQuotasTask(service);
+    }
+
+    @Override
+    public String getType() {
+        return type;
+    }
+}
diff --git a/mailbox/tools/quota-recompute/src/test/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTaskSerializationTest.java b/mailbox/tools/quota-recompute/src/test/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTaskSerializationTest.java
new file mode 100644
index 0000000..9eb7405
--- /dev/null
+++ b/mailbox/tools/quota-recompute/src/test/java/org/apache/james/mailbox/quota/task/RecomputeCurrentQuotasTaskSerializationTest.java
@@ -0,0 +1,61 @@
+/****************************************************************
+ * 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.mailbox.quota.task;
+
+import static org.mockito.Mockito.mock;
+
+import java.time.Instant;
+
+import org.apache.james.JsonSerializationVerifier;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.ImmutableList;
+
+class RecomputeCurrentQuotasTaskSerializationTest {
+    static final Instant TIMESTAMP = Instant.parse("2018-11-13T12:00:55Z");
+    static final String QUOTA_ROOT_AS_STRING = "bob@localhost";
+
+    static final RecomputeCurrentQuotasService SERVICE = mock(RecomputeCurrentQuotasService.class);
+    static final RecomputeCurrentQuotasTask TASK = new RecomputeCurrentQuotasTask(SERVICE);
+    static final String SERIALIZED_TASK = "{\"type\": \"recompute-current-quotas\"}";
+    static final RecomputeCurrentQuotasTask.Details DETAILS = new RecomputeCurrentQuotasTask.Details(TIMESTAMP, 12, ImmutableList.of(QUOTA_ROOT_AS_STRING));
+    static final String SERIALIZED_ADDITIONAL_INFORMATION = "{" +
+        "  \"type\":\"recompute-current-quotas\"," +
+        "  \"processedQuotaRoots\":12," +
+        "  \"failedQuotaRoots\":[\"bob@localhost\"]," +
+        "  \"timestamp\":\"2018-11-13T12:00:55Z\"" +
+        "}";
+
+    @Test
+    void taskShouldBeSerializable() throws Exception {
+        JsonSerializationVerifier.dtoModule(RecomputeCurrentQuotasTaskDTO.module(SERVICE))
+            .bean(TASK)
+            .json(SERIALIZED_TASK)
+            .verify();
+    }
+
+    @Test
+    void additionalInformationShouldBeSerializable() throws Exception {
+        JsonSerializationVerifier.dtoModule(RecomputeCurrentQuotasTaskAdditionalInformationDTO.MODULE)
+            .bean(DETAILS)
+            .json(SERIALIZED_ADDITIONAL_INFORMATION)
+            .verify();
+    }
+}


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