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 4a7dfcbf03bc4dbfb3662f08af44496f4b847b37 Author: Rene Cordier <rcord...@linagora.com> AuthorDate: Fri Apr 10 15:05:40 2020 +0700 JAMES-3138 Add getCurrentQuotas in CurrentQuotaManager --- .../apache/james/mailbox/model/CurrentQuotas.java | 4 +++ .../james/mailbox/quota/CurrentQuotaManager.java | 2 ++ .../quota/CassandraCurrentQuotaManager.java | 37 ++++++++++++++++------ .../mailbox/jpa/quota/JpaCurrentQuotaManager.java | 8 +++++ .../quota/InMemoryCurrentQuotaManager.java | 6 ++++ .../quota/InMemoryCurrentQuotaManagerTest.java | 19 +++++++++++ .../store/quota/StoreCurrentQuotaManagerTest.java | 37 ++++++++++++++++++---- 7 files changed, 97 insertions(+), 16 deletions(-) diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/CurrentQuotas.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/CurrentQuotas.java index e155841..3b82866 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/CurrentQuotas.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/CurrentQuotas.java @@ -28,6 +28,10 @@ public class CurrentQuotas { private final QuotaCountUsage count; private final QuotaSizeUsage size; + public static CurrentQuotas emptyQuotas() { + return new CurrentQuotas(QuotaCountUsage.count(0L), QuotaSizeUsage.size(0L)); + } + public CurrentQuotas(QuotaCountUsage count, QuotaSizeUsage size) { this.count = count; this.size = size; diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/quota/CurrentQuotaManager.java b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/CurrentQuotaManager.java index f1f3d41..1e84e09 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/quota/CurrentQuotaManager.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/CurrentQuotaManager.java @@ -21,6 +21,7 @@ package org.apache.james.mailbox.quota; import org.apache.james.core.quota.QuotaCountUsage; import org.apache.james.core.quota.QuotaSizeUsage; +import org.apache.james.mailbox.model.CurrentQuotas; import org.apache.james.mailbox.model.QuotaRoot; import org.reactivestreams.Publisher; @@ -33,4 +34,5 @@ public interface CurrentQuotaManager { Publisher<QuotaSizeUsage> getCurrentStorage(QuotaRoot quotaRoot); + Publisher<CurrentQuotas> getCurrentQuotas(QuotaRoot quotaRoot); } diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraCurrentQuotaManager.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraCurrentQuotaManager.java index a4ba974..fcda0ca 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraCurrentQuotaManager.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraCurrentQuotaManager.java @@ -25,6 +25,9 @@ import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; import static com.datastax.driver.core.querybuilder.QueryBuilder.incr; import static com.datastax.driver.core.querybuilder.QueryBuilder.select; import static com.datastax.driver.core.querybuilder.QueryBuilder.update; +import static org.apache.james.mailbox.cassandra.table.CassandraCurrentQuota.MESSAGE_COUNT; +import static org.apache.james.mailbox.cassandra.table.CassandraCurrentQuota.STORAGE; +import static org.apache.james.mailbox.cassandra.table.CassandraCurrentQuota.TABLE_NAME; import javax.inject.Inject; @@ -32,6 +35,7 @@ import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor; import org.apache.james.core.quota.QuotaCountUsage; import org.apache.james.core.quota.QuotaSizeUsage; import org.apache.james.mailbox.cassandra.table.CassandraCurrentQuota; +import org.apache.james.mailbox.model.CurrentQuotas; import org.apache.james.mailbox.model.QuotaOperation; import org.apache.james.mailbox.model.QuotaRoot; import org.apache.james.mailbox.store.quota.StoreCurrentQuotaManager; @@ -48,23 +52,27 @@ public class CassandraCurrentQuotaManager implements StoreCurrentQuotaManager { private final PreparedStatement decreaseStatement; private final PreparedStatement getCurrentMessageCountStatement; private final PreparedStatement getCurrentStorageStatement; + private final PreparedStatement getCurrentQuotasStatement; @Inject public CassandraCurrentQuotaManager(Session session) { this.cassandraAsyncExecutor = new CassandraAsyncExecutor(session); - this.increaseStatement = session.prepare(update(CassandraCurrentQuota.TABLE_NAME) - .with(incr(CassandraCurrentQuota.MESSAGE_COUNT, bindMarker())) - .and(incr(CassandraCurrentQuota.STORAGE, bindMarker())) + this.increaseStatement = session.prepare(update(TABLE_NAME) + .with(incr(MESSAGE_COUNT, bindMarker())) + .and(incr(STORAGE, bindMarker())) .where(eq(CassandraCurrentQuota.QUOTA_ROOT, bindMarker()))); - this.decreaseStatement = session.prepare(update(CassandraCurrentQuota.TABLE_NAME) - .with(decr(CassandraCurrentQuota.MESSAGE_COUNT, bindMarker())) - .and(decr(CassandraCurrentQuota.STORAGE, bindMarker())) + this.decreaseStatement = session.prepare(update(TABLE_NAME) + .with(decr(MESSAGE_COUNT, bindMarker())) + .and(decr(STORAGE, bindMarker())) .where(eq(CassandraCurrentQuota.QUOTA_ROOT, bindMarker()))); - this.getCurrentMessageCountStatement = session.prepare(select(CassandraCurrentQuota.MESSAGE_COUNT) - .from(CassandraCurrentQuota.TABLE_NAME) + this.getCurrentMessageCountStatement = session.prepare(select(MESSAGE_COUNT) + .from(TABLE_NAME) .where(eq(CassandraCurrentQuota.QUOTA_ROOT, bindMarker()))); - this.getCurrentStorageStatement = session.prepare(select(CassandraCurrentQuota.STORAGE) - .from(CassandraCurrentQuota.TABLE_NAME) + this.getCurrentStorageStatement = session.prepare(select(STORAGE) + .from(TABLE_NAME) + .where(eq(CassandraCurrentQuota.QUOTA_ROOT, bindMarker()))); + this.getCurrentQuotasStatement = session.prepare(select(MESSAGE_COUNT, STORAGE) + .from(TABLE_NAME) .where(eq(CassandraCurrentQuota.QUOTA_ROOT, bindMarker()))); } @@ -95,4 +103,13 @@ public class CassandraCurrentQuotaManager implements StoreCurrentQuotaManager { .map(row -> QuotaSizeUsage.size(row.getLong(CassandraCurrentQuota.STORAGE))) .defaultIfEmpty(QuotaSizeUsage.size(0L)); } + + @Override + public Mono<CurrentQuotas> getCurrentQuotas(QuotaRoot quotaRoot) { + return cassandraAsyncExecutor.executeSingleRow(getCurrentQuotasStatement.bind(quotaRoot.getValue())) + .map(row -> new CurrentQuotas( + QuotaCountUsage.count(row.getLong(MESSAGE_COUNT)), + QuotaSizeUsage.size(row.getLong(STORAGE)))) + .defaultIfEmpty(CurrentQuotas.emptyQuotas()); + } } diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JpaCurrentQuotaManager.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JpaCurrentQuotaManager.java index f56bab0..f79f4a1 100644 --- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JpaCurrentQuotaManager.java +++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JpaCurrentQuotaManager.java @@ -29,6 +29,7 @@ import org.apache.james.backends.jpa.TransactionRunner; import org.apache.james.core.quota.QuotaCountUsage; import org.apache.james.core.quota.QuotaSizeUsage; import org.apache.james.mailbox.jpa.quota.model.JpaCurrentQuota; +import org.apache.james.mailbox.model.CurrentQuotas; import org.apache.james.mailbox.model.QuotaOperation; import org.apache.james.mailbox.model.QuotaRoot; import org.apache.james.mailbox.store.quota.StoreCurrentQuotaManager; @@ -67,6 +68,13 @@ public class JpaCurrentQuotaManager implements StoreCurrentQuotaManager { .orElse(QuotaSizeUsage.size(NO_STORED_BYTES))); } + public Mono<CurrentQuotas> getCurrentQuotas(QuotaRoot quotaRoot) { + EntityManager entityManager = entityManagerFactory.createEntityManager(); + return Mono.fromCallable(() -> Optional.ofNullable(retrieveUserQuota(entityManager, quotaRoot)) + .map(jpaCurrentQuota -> new CurrentQuotas(jpaCurrentQuota.getMessageCount(), jpaCurrentQuota.getSize())) + .orElse(CurrentQuotas.emptyQuotas())); + } + @Override public Mono<Void> increase(QuotaOperation quotaOperation) { return Mono.fromRunnable(() -> diff --git a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManager.java b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManager.java index 326640c..32b55cc 100644 --- a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManager.java +++ b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManager.java @@ -77,6 +77,12 @@ public class InMemoryCurrentQuotaManager implements StoreCurrentQuotaManager { .onErrorMap(this::wrapAsMailboxException); } + @Override + public Mono<CurrentQuotas> getCurrentQuotas(QuotaRoot quotaRoot) { + return Mono.fromCallable(() -> quotaCache.get(quotaRoot).get()) + .onErrorMap(this::wrapAsMailboxException); + } + private Mono<Void> updateQuota(QuotaRoot quotaRoot, UnaryOperator<CurrentQuotas> quotaFunction) { return Mono.fromCallable(() -> quotaCache.get(quotaRoot).updateAndGet(quotaFunction)) .onErrorMap(this::wrapAsMailboxException) diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManagerTest.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManagerTest.java index 9320964..99d1191 100644 --- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManagerTest.java +++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManagerTest.java @@ -78,4 +78,23 @@ class InMemoryCurrentQuotaManagerTest { assertThat(testee.getCurrentMessageCount(QUOTA_ROOT).block()).isEqualTo(QuotaCountUsage.count(28)); assertThat(testee.getCurrentStorage(QUOTA_ROOT).block()).isEqualTo(QuotaSizeUsage.size(612)); } + + @Test + void getCurrentQuotasShouldReturnRecalculateSizeWhenEntryIsNotInitialized() throws Exception { + when(mockedCurrentQuotaCalculator.recalculateCurrentQuotas(QUOTA_ROOT, null)) + .thenReturn(CURRENT_QUOTAS); + + assertThat(testee.getCurrentQuotas(QUOTA_ROOT).block()).isEqualTo(CURRENT_QUOTAS); + } + + @Test + void getCurrentQuotasShouldReRetrieveStoredQuotasWhenCalculateOnUnknownQuotaIsTrue() throws Exception { + when(mockedCurrentQuotaCalculator.recalculateCurrentQuotas(QUOTA_ROOT, null)) + .thenReturn(CURRENT_QUOTAS); + + QuotaOperation quotaOperation = new QuotaOperation(QUOTA_ROOT, QuotaCountUsage.count(10), QuotaSizeUsage.size(100)); + testee.increase(quotaOperation).block(); + + assertThat(testee.getCurrentQuotas(QUOTA_ROOT).block()).isEqualTo(new CurrentQuotas(QuotaCountUsage.count(28), QuotaSizeUsage.size(612))); + } } diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreCurrentQuotaManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreCurrentQuotaManagerTest.java index 02701fb..74ca11c 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreCurrentQuotaManagerTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreCurrentQuotaManagerTest.java @@ -25,15 +25,20 @@ import java.util.Optional; import org.apache.james.core.quota.QuotaCountUsage; import org.apache.james.core.quota.QuotaSizeUsage; +import org.apache.james.mailbox.model.CurrentQuotas; import org.apache.james.mailbox.model.QuotaOperation; import org.apache.james.mailbox.model.QuotaRoot; +import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.github.fge.lambdas.Throwing; + import reactor.core.publisher.Mono; public abstract class StoreCurrentQuotaManagerTest { private static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("benwa", Optional.empty()); + private static final CurrentQuotas CURRENT_QUOTAS = new CurrentQuotas(QuotaCountUsage.count(10), QuotaSizeUsage.size(100)); protected abstract StoreCurrentQuotaManager provideTestee(); @@ -50,11 +55,24 @@ public abstract class StoreCurrentQuotaManagerTest { } @Test + void getCurrentMessageCountShouldReturnZeroByDefault() throws Exception { + assertThat(Mono.from(testee.getCurrentMessageCount(QUOTA_ROOT)).block()).isEqualTo(QuotaCountUsage.count(0)); + } + + @Test + void getCurrentQuotasShouldReturnZeroByDefault() { + assertThat(Mono.from(testee.getCurrentQuotas(QUOTA_ROOT)).block()).isEqualTo(CurrentQuotas.emptyQuotas()); + } + + @Test void increaseShouldWork() throws Exception { testee.increase(new QuotaOperation(QUOTA_ROOT, QuotaCountUsage.count(10), QuotaSizeUsage.size(100))).block(); - assertThat(Mono.from(testee.getCurrentMessageCount(QUOTA_ROOT)).block()).isEqualTo(QuotaCountUsage.count(10)); - assertThat(Mono.from(testee.getCurrentStorage(QUOTA_ROOT)).block()).isEqualTo(QuotaSizeUsage.size(100)); + SoftAssertions.assertSoftly(Throwing.consumer(softly -> { + softly.assertThat(Mono.from(testee.getCurrentQuotas(QUOTA_ROOT)).block()).isEqualTo(CURRENT_QUOTAS); + softly.assertThat(Mono.from(testee.getCurrentMessageCount(QUOTA_ROOT)).block()).isEqualTo(QuotaCountUsage.count(10)); + softly.assertThat(Mono.from(testee.getCurrentStorage(QUOTA_ROOT)).block()).isEqualTo(QuotaSizeUsage.size(100)); + })); } @Test @@ -63,15 +81,22 @@ public abstract class StoreCurrentQuotaManagerTest { testee.decrease(new QuotaOperation(QUOTA_ROOT, QuotaCountUsage.count(10), QuotaSizeUsage.size(100))).block(); - assertThat(Mono.from(testee.getCurrentMessageCount(QUOTA_ROOT)).block()).isEqualTo(QuotaCountUsage.count(10)); - assertThat(Mono.from(testee.getCurrentStorage(QUOTA_ROOT)).block()).isEqualTo(QuotaSizeUsage.size(100)); + SoftAssertions.assertSoftly(Throwing.consumer(softly -> { + softly.assertThat(Mono.from(testee.getCurrentQuotas(QUOTA_ROOT)).block()).isEqualTo(CURRENT_QUOTAS); + softly.assertThat(Mono.from(testee.getCurrentMessageCount(QUOTA_ROOT)).block()).isEqualTo(QuotaCountUsage.count(10)); + softly.assertThat(Mono.from(testee.getCurrentStorage(QUOTA_ROOT)).block()).isEqualTo(QuotaSizeUsage.size(100)); + })); } @Test void decreaseShouldNotFailWhenItLeadsToNegativeValues() throws Exception { testee.decrease(new QuotaOperation(QUOTA_ROOT, QuotaCountUsage.count(10), QuotaSizeUsage.size(100))).block(); - assertThat(Mono.from(testee.getCurrentMessageCount(QUOTA_ROOT)).block()).isEqualTo(QuotaCountUsage.count(-10)); - assertThat(Mono.from(testee.getCurrentStorage(QUOTA_ROOT)).block()).isEqualTo(QuotaSizeUsage.size(-100)); + SoftAssertions.assertSoftly(Throwing.consumer(softly -> { + softly.assertThat(Mono.from(testee.getCurrentQuotas(QUOTA_ROOT)).block()) + .isEqualTo(new CurrentQuotas(QuotaCountUsage.count(-10), QuotaSizeUsage.size(-100))); + softly.assertThat(Mono.from(testee.getCurrentMessageCount(QUOTA_ROOT)).block()).isEqualTo(QuotaCountUsage.count(-10)); + softly.assertThat(Mono.from(testee.getCurrentStorage(QUOTA_ROOT)).block()).isEqualTo(QuotaSizeUsage.size(-100)); + })); } } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org