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 <rcord...@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-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org