JAMES-2399 include listener name in aggregate id to prevent sharing events between two QuotaMailingListeners
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/8e5f2cc2 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/8e5f2cc2 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/8e5f2cc2 Branch: refs/heads/master Commit: 8e5f2cc25c5e900f85fc8a1f7bada57a3a71ec44 Parents: 8040919 Author: Matthieu Baechler <[email protected]> Authored: Thu May 17 16:30:26 2018 +0200 Committer: Matthieu Baechler <[email protected]> Committed: Tue May 22 10:02:27 2018 +0200 ---------------------------------------------------------------------- .../dto/QuotaThresholdChangedEventDTO.java | 15 +++--- .../mailbox/quota/cassandra/dto/DTOTest.java | 9 ++-- .../src/test/resources/json/event.json | 2 +- .../src/test/resources/json/event2.json | 2 +- .../src/test/resources/json/event3.json | 2 +- .../src/test/resources/json/event4.json | 2 +- mailbox/plugin/quota-mailing/pom.xml | 4 ++ .../QuotaMailingListenerConfiguration.java | 54 ++++++++++++++++++-- .../mailing/aggregates/UserQuotaThresholds.java | 43 +++++++++++++--- .../DetectThresholdCrossingHandler.java | 4 +- .../QuotaMailingListenerConfigurationTest.java | 9 ++++ .../aggregates/UserQuotaThresholdsTest.java | 43 +++++++++++++++- .../org/apache/james/CassandraJmapTestRule.java | 5 +- .../org/apache/james/MemoryJmapTestRule.java | 8 +-- .../CassandraGetMessageListMethodTest.java | 4 +- .../src/test/resources/listeners.xml | 10 ++++ .../integration/GetMessageListMethodTest.java | 1 + .../methods/integration/QuotaMailingTest.java | 19 +++++-- .../memory/MemoryGetMessageListMethodTest.java | 3 +- .../src/test/resources/listeners.xml | 10 ++++ 20 files changed, 209 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java index f229e2c..6d1ab84 100644 --- a/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java +++ b/mailbox/plugin/quota-mailing-cassandra/src/main/java/org/apache/james/mailbox/quota/cassandra/dto/QuotaThresholdChangedEventDTO.java @@ -19,7 +19,6 @@ package org.apache.james.mailbox.quota.cassandra.dto; -import org.apache.james.core.User; import org.apache.james.eventsourcing.EventId; import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO; import org.apache.james.mailbox.quota.mailing.aggregates.UserQuotaThresholds; @@ -35,7 +34,7 @@ class QuotaThresholdChangedEventDTO implements EventDTO { public static QuotaThresholdChangedEventDTO from(QuotaThresholdChangedEvent event, String type) { return new QuotaThresholdChangedEventDTO( type, event.eventId().serialize(), - event.getAggregateId().getUser().asString(), + event.getAggregateId().asAggregateKey(), QuotaDTO.from(event.getSizeQuota()), QuotaDTO.from(event.getCountQuota()), HistoryEvolutionDTO.toDto(event.getSizeHistoryEvolution()), @@ -44,7 +43,7 @@ class QuotaThresholdChangedEventDTO implements EventDTO { private final String type; private final int eventId; - private final String user; + private final String aggregateId; private final QuotaDTO sizeQuota; private final QuotaDTO countQuota; private final HistoryEvolutionDTO sizeEvolution; @@ -54,14 +53,14 @@ class QuotaThresholdChangedEventDTO implements EventDTO { private QuotaThresholdChangedEventDTO( @JsonProperty("type") String type, @JsonProperty("eventId") int eventId, - @JsonProperty("user") String user, + @JsonProperty("aggregateId") String aggregateId, @JsonProperty("sizeQuota") QuotaDTO sizeQuota, @JsonProperty("countQuota") QuotaDTO countQuota, @JsonProperty("sizeEvolution") HistoryEvolutionDTO sizeEvolution, @JsonProperty("countEvolution") HistoryEvolutionDTO countEvolution) { this.type = type; this.eventId = eventId; - this.user = user; + this.aggregateId = aggregateId; this.sizeQuota = sizeQuota; this.countQuota = countQuota; this.sizeEvolution = sizeEvolution; @@ -76,8 +75,8 @@ class QuotaThresholdChangedEventDTO implements EventDTO { return eventId; } - public String getUser() { - return user; + public String getAggregateId() { + return aggregateId; } public QuotaDTO getSizeQuota() { @@ -105,6 +104,6 @@ class QuotaThresholdChangedEventDTO implements EventDTO { countEvolution.toHistoryEvolution(), sizeQuota.asSizeQuota(), countQuota.asCountQuota(), - UserQuotaThresholds.Id.from(User.fromUsername(user))); + UserQuotaThresholds.Id.fromKey(aggregateId)); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java index ca063d9..5ed61ab 100644 --- a/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java +++ b/mailbox/plugin/quota-mailing-cassandra/src/test/java/org/apache/james/mailbox/quota/cassandra/dto/DTOTest.java @@ -49,20 +49,21 @@ class DTOTest { static final Quota<QuotaSize> SIZE_QUOTA = Quota.<QuotaSize>builder().used(QuotaSize.size(23)).computedLimit(QuotaSize.size(33)).build(); static final Quota<QuotaCount> COUNT_QUOTA = Quota.<QuotaCount>builder().used(QuotaCount.count(12)).computedLimit(QuotaCount.count(45)).build(); static final Instant INSTANT = Instant.ofEpochMilli(45554); + public static final String DEFAULT_LISTENER_NAME = "default"; static final QuotaThresholdChangedEvent EVENT = new QuotaThresholdChangedEvent( EventId.first(), HistoryEvolution.noChanges(), HistoryEvolution.noChanges(), SIZE_QUOTA, COUNT_QUOTA, - UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"))); + UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"), DEFAULT_LISTENER_NAME)); static final QuotaThresholdChangedEvent EVENT_2 = new QuotaThresholdChangedEvent( EventId.first(), HistoryEvolution.lowerThresholdReached(new QuotaThresholdChange(_75, INSTANT)), HistoryEvolution.noChanges(), SIZE_QUOTA, Quota.<QuotaCount>builder().used(QuotaCount.count(12)).computedLimit(QuotaCount.unlimited()).build(), - UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"))); + UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"), DEFAULT_LISTENER_NAME)); static final QuotaThresholdChangedEvent EVENT_3 = new QuotaThresholdChangedEvent( EventId.first(), HistoryEvolution.lowerThresholdReached(new QuotaThresholdChange(_75, INSTANT)), @@ -70,7 +71,7 @@ class DTOTest { HistoryEvolution.HighestThresholdRecentness.NotAlreadyReachedDuringGracePeriod), SIZE_QUOTA, Quota.<QuotaCount>builder().used(QuotaCount.count(12)).computedLimit(QuotaCount.unlimited()).build(), - UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"))); + UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"), DEFAULT_LISTENER_NAME)); static final QuotaThresholdChangedEvent EVENT_4 = new QuotaThresholdChangedEvent( EventId.first(), HistoryEvolution.lowerThresholdReached(new QuotaThresholdChange(_75, INSTANT)), @@ -78,7 +79,7 @@ class DTOTest { HistoryEvolution.HighestThresholdRecentness.AlreadyReachedDuringGracePeriod), SIZE_QUOTA, Quota.<QuotaCount>builder().used(QuotaCount.count(12)).computedLimit(QuotaCount.unlimited()).build(), - UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"))); + UserQuotaThresholds.Id.from(User.fromUsername("[email protected]"), DEFAULT_LISTENER_NAME)); static final String EVENT_JSON = ClassLoaderUtils.getSystemResourceAsString("json/event.json"); static final String EVENT_JSON_2 = ClassLoaderUtils.getSystemResourceAsString("json/event2.json"); http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event.json ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event.json b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event.json index 4449047..93a78ce 100644 --- a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event.json +++ b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event.json @@ -1,7 +1,7 @@ { "type": "quota-threshold-change", "eventId": 0, - "user": "[email protected]", + "aggregateId":"QuotaThreasholdEvents/default/[email protected]", "sizeQuota": { "used": 23, "limit": 33 http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event2.json ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event2.json b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event2.json index b20cfab..6a8703d 100644 --- a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event2.json +++ b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event2.json @@ -1,7 +1,7 @@ { "type":"quota-threshold-change", "eventId":0, - "user":"[email protected]", + "aggregateId":"QuotaThreasholdEvents/default/[email protected]", "sizeQuota":{ "used":23, "limit":33 http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event3.json ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event3.json b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event3.json index 4bda126..552ce29 100644 --- a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event3.json +++ b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event3.json @@ -1,7 +1,7 @@ { "type":"quota-threshold-change", "eventId":0, - "user":"[email protected]", + "aggregateId":"QuotaThreasholdEvents/default/[email protected]", "sizeQuota":{ "used":23, "limit":33 http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event4.json ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event4.json b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event4.json index 0852dc5..ff62e9c 100644 --- a/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event4.json +++ b/mailbox/plugin/quota-mailing-cassandra/src/test/resources/json/event4.json @@ -1,7 +1,7 @@ { "type":"quota-threshold-change", "eventId":0, - "user":"[email protected]", + "aggregateId":"QuotaThreasholdEvents/default/[email protected]", "sizeQuota":{ "used":23, "limit":33 http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/pom.xml ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/pom.xml b/mailbox/plugin/quota-mailing/pom.xml index 3cda088..65b8f62 100644 --- a/mailbox/plugin/quota-mailing/pom.xml +++ b/mailbox/plugin/quota-mailing/pom.xml @@ -94,6 +94,10 @@ <artifactId>james-server-util</artifactId> </dependency> <dependency> + <groupId>commons-configuration</groupId> + <artifactId>commons-configuration</artifactId> + </dependency> + <dependency> <groupId>com.github.spullara.mustache.java</groupId> <artifactId>compiler</artifactId> </dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java index 8f680b4..6f2e7a6 100644 --- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java +++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfiguration.java @@ -44,6 +44,7 @@ public class QuotaMailingListenerConfiguration { String GRACE_PERIOD = "gracePeriod"; String THRESHOLDS = "thresholds.threshold"; String ROOT_KEY = ""; + String NAME = "name"; } public static QuotaMailingListenerConfiguration from(HierarchicalConfiguration config) { @@ -52,9 +53,14 @@ public class QuotaMailingListenerConfiguration { .subjectTemplate(readSubjectTemplate(config)) .bodyTemplate(readBodyTemplate(config)) .gracePeriod(readGracePeriod(config)) + .name(readName(config)) .build(); } + private static Optional<String> readName(HierarchicalConfiguration config) { + return Optional.ofNullable(config.getString(XmlKeys.NAME, null)); + } + private static Optional<String> readSubjectTemplate(HierarchicalConfiguration config) { return Optional.ofNullable(config.getString(XmlKeys.SUBJECT_TEMPLATE, null)); } @@ -82,12 +88,14 @@ public class QuotaMailingListenerConfiguration { private Optional<Duration> gradePeriod; private Optional<String> bodyTemplate; private Optional<String> subjectTemplate; + private Optional<String> name; private Builder() { thresholds = ImmutableList.builder(); gradePeriod = Optional.empty(); bodyTemplate = Optional.empty(); subjectTemplate = Optional.empty(); + name = Optional.empty(); } public Builder addThreshold(QuotaThreshold quotaThreshold) { @@ -122,33 +130,67 @@ public class QuotaMailingListenerConfiguration { return this; } + public Builder gracePeriod(Optional<Duration> duration) { + duration.ifPresent(this::gracePeriod); + return this; + } + + public Builder bodyTemplate(Optional<String> bodyTemplate) { + bodyTemplate.ifPresent(this::bodyTemplate); + return this; + } + + public Builder subjectTemplate(Optional<String> subjectTemplate) { + subjectTemplate.ifPresent(this::subjectTemplate); + return this; + } + + public Builder name(String name) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(name), "Pass a non null/empty name"); + this.name = Optional.of(name); + return this; + } + + public Builder name(Optional<String> name) { + name.ifPresent(this::name); + return this; + } + public QuotaMailingListenerConfiguration build() { return new QuotaMailingListenerConfiguration( new QuotaThresholds(thresholds.build()), gradePeriod.orElse(DEFAULT_GRACE_PERIOD), bodyTemplate.orElse(DEFAULT_BODY_TEMPLATE), - subjectTemplate.orElse(DEFAULT_SUBJECT_TEMPLATE)); + subjectTemplate.orElse(DEFAULT_SUBJECT_TEMPLATE), + name.orElse(DEFAULT_NAME)); } } public static final String DEFAULT_BODY_TEMPLATE = FileSystem.CLASSPATH_PROTOCOL + "//templates/QuotaThresholdMailBody.mustache"; public static final String DEFAULT_SUBJECT_TEMPLATE = FileSystem.CLASSPATH_PROTOCOL + "//templates/QuotaThresholdMailSubject.mustache"; public static final Duration DEFAULT_GRACE_PERIOD = Duration.ofDays(1); + private static final String DEFAULT_NAME = "default"; public static Builder builder() { return new Builder(); } + public static QuotaMailingListenerConfiguration defaultConfiguration() { + return builder().build(); + } + private final QuotaThresholds thresholds; private final Duration gracePeriod; private final String bodyTemplate; private final String subjectTemplate; + private final String name; - private QuotaMailingListenerConfiguration(QuotaThresholds thresholds, Duration gracePeriod, String bodyTemplate, String subjectTemplate) { + private QuotaMailingListenerConfiguration(QuotaThresholds thresholds, Duration gracePeriod, String bodyTemplate, String subjectTemplate, String name) { this.thresholds = thresholds; this.gracePeriod = gracePeriod; this.bodyTemplate = bodyTemplate; this.subjectTemplate = subjectTemplate; + this.name = name; } public QuotaThresholds getThresholds() { @@ -167,6 +209,10 @@ public class QuotaMailingListenerConfiguration { return subjectTemplate; } + public String getName() { + return name; + } + @Override public final boolean equals(Object o) { if (o instanceof QuotaMailingListenerConfiguration) { @@ -175,6 +221,7 @@ public class QuotaMailingListenerConfiguration { return Objects.equals(this.thresholds, that.thresholds) && Objects.equals(this.gracePeriod, that.gracePeriod) && Objects.equals(this.bodyTemplate, that.bodyTemplate) + && Objects.equals(this.name, that.name) && Objects.equals(this.subjectTemplate, that.subjectTemplate); } return false; @@ -182,7 +229,7 @@ public class QuotaMailingListenerConfiguration { @Override public final int hashCode() { - return Objects.hash(thresholds, gracePeriod, bodyTemplate, subjectTemplate); + return Objects.hash(thresholds, gracePeriod, bodyTemplate, subjectTemplate, name); } @Override @@ -192,6 +239,7 @@ public class QuotaMailingListenerConfiguration { .add("gracePeriod", gracePeriod) .add("bodyTemplate", bodyTemplate) .add("subjectTemplate", subjectTemplate) + .add("name", name) .toString(); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholds.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholds.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholds.java index ae67d30..5ae7835 100644 --- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholds.java +++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholds.java @@ -41,20 +41,42 @@ import org.apache.james.mailbox.quota.model.QuotaThresholds; import org.apache.james.util.OptionalUtils; import com.github.steveash.guavate.Guavate; +import com.google.common.base.Joiner; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; public class UserQuotaThresholds { public static class Id implements AggregateId { - public static Id from(User user) { - return new Id(user); + private static final int PREFIX_INDEX = 0; + private static final int NAME_INDEX = 1; + private static final int USER_INDEX = 2; + private static final String SEPARATOR = "/"; + private static final String PREFIX = "QuotaThreasholdEvents"; + + public static Id fromKey(String key) { + List<String> keyParts = Splitter.on(SEPARATOR).splitToList(key); + if (keyParts.size() != 3 || !keyParts.get(PREFIX_INDEX).equals(PREFIX)) { + throw new IllegalArgumentException(); + } + return new Id(User.fromUsername(keyParts.get(USER_INDEX)), keyParts.get(NAME_INDEX)); + } + + public static Id from(User user, String name) { + return new Id(user, name); } private final User user; + private final String name; - private Id(User user) { + private Id(User user, String name) { + Preconditions.checkArgument(!user.asString().contains(SEPARATOR)); + Preconditions.checkArgument(!name.contains(SEPARATOR)); this.user = user; + this.name = name; } public User getUser() { @@ -63,7 +85,7 @@ public class UserQuotaThresholds { @Override public String asAggregateKey() { - return "QuotaThreasholdEvents-" + user.asString(); + return Joiner.on(SEPARATOR).join(PREFIX, name, user.asString()); } @Override @@ -71,14 +93,23 @@ public class UserQuotaThresholds { if (o instanceof Id) { Id id = (Id) o; - return Objects.equals(this.user, id.user); + return Objects.equals(this.user, id.user) + && Objects.equals(this.name, id.name); } return false; } @Override public final int hashCode() { - return Objects.hash(user); + return Objects.hash(user, name); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("user", user) + .add("name", name) + .toString(); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/commands/DetectThresholdCrossingHandler.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/commands/DetectThresholdCrossingHandler.java b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/commands/DetectThresholdCrossingHandler.java index b44ab3e..54a9db3 100644 --- a/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/commands/DetectThresholdCrossingHandler.java +++ b/mailbox/plugin/quota-mailing/src/main/java/org/apache/james/mailbox/quota/mailing/commands/DetectThresholdCrossingHandler.java @@ -32,10 +32,12 @@ public class DetectThresholdCrossingHandler implements CommandHandler<DetectThre private final EventStore eventStore; private final QuotaMailingListenerConfiguration quotaMailingListenerConfiguration; + private final String listenerName; public DetectThresholdCrossingHandler(EventStore eventStore, QuotaMailingListenerConfiguration quotaMailingListenerConfiguration) { this.eventStore = eventStore; this.quotaMailingListenerConfiguration = quotaMailingListenerConfiguration; + this.listenerName = quotaMailingListenerConfiguration.getName(); } @Override @@ -45,7 +47,7 @@ public class DetectThresholdCrossingHandler implements CommandHandler<DetectThre } private UserQuotaThresholds loadAggregate(DetectThresholdCrossing command) { - UserQuotaThresholds.Id aggregateId = UserQuotaThresholds.Id.from(command.getUser()); + UserQuotaThresholds.Id aggregateId = UserQuotaThresholds.Id.from(command.getUser(), listenerName); History history = eventStore.getEventsOfAggregate(aggregateId); return UserQuotaThresholds.fromEvents(aggregateId, history); } http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java index 50a4044..1668640 100644 --- a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/QuotaMailingListenerConfigurationTest.java @@ -57,6 +57,7 @@ public class QuotaMailingListenerConfigurationTest { " <gracePeriod>3 days</gracePeriod>\n" + " <subjectTemplate>" + SUBJECT_TEMPLATE + "</subjectTemplate>\n" + " <bodyTemplate>" + BODY_TEMPLATE + "</bodyTemplate>\n" + + " <name>listener-name</name>\n" + "</configuration>")); QuotaMailingListenerConfiguration result = QuotaMailingListenerConfiguration.from(xmlConfiguration); @@ -68,6 +69,7 @@ public class QuotaMailingListenerConfigurationTest { .gracePeriod(Duration.ofDays(3)) .subjectTemplate(SUBJECT_TEMPLATE) .bodyTemplate(BODY_TEMPLATE) + .name("listener-name") .build()); } @@ -106,6 +108,13 @@ public class QuotaMailingListenerConfigurationTest { } @Test + public void defaultConfigurationShouldUseDefaultAsListenerName() throws Exception { + QuotaMailingListenerConfiguration result = QuotaMailingListenerConfiguration.defaultConfiguration(); + + assertThat(result.getName()).isEqualTo("default"); + } + + @Test public void fromShouldThrowOnNonParsableGracePeriod() throws Exception { DefaultConfigurationBuilder xmlConfiguration = new DefaultConfigurationBuilder(); xmlConfiguration.load(toStream( http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholdsTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholdsTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholdsTest.java index 45aef96..52d7ff4 100644 --- a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholdsTest.java +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/aggregates/UserQuotaThresholdsTest.java @@ -20,6 +20,7 @@ package org.apache.james.mailbox.quota.mailing.aggregates; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import org.apache.james.core.User; import org.junit.jupiter.api.Test; @@ -39,9 +40,47 @@ public class UserQuotaThresholdsTest { @Test public void asAggregationKeyShouldConvertAggregateToAStringRepresentation() { - assertThat(UserQuotaThresholds.Id.from(BOB) + assertThat(UserQuotaThresholds.Id.from(BOB, "listenerName") .asAggregateKey()) - .isEqualTo("QuotaThreasholdEvents-bob@domain"); + .isEqualTo("QuotaThreasholdEvents/listenerName/bob@domain"); } + @Test + public void fromShouldThrowWhenUserWithSlash() { + assertThatThrownBy(() -> UserQuotaThresholds.Id.from(User.fromUsername("foo/bar@domain"), "listenerName")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void fromShouldThrowWhenDomainWithSlash() { + assertThatThrownBy(() -> UserQuotaThresholds.Id.from(User.fromUsername("foo.bar@dom/ain"), "listenerName")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void fromShouldThrowWhenListenerNameWithSlash() { + assertThatThrownBy(() -> UserQuotaThresholds.Id.from(BOB, "listener/Name")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void asAggregationKeyShouldParseAsOriginalPojo() { + UserQuotaThresholds.Id id = UserQuotaThresholds.Id.from(BOB, "listenerName"); + assertThat(UserQuotaThresholds.Id.fromKey(id.asAggregateKey())).isEqualTo(id); + } + + @Test + public void fromKeyShouldThrowWhenLessThan3Parts() { + assertThatThrownBy(() -> UserQuotaThresholds.Id.fromKey("1/2")).isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void fromKeyShouldThrowWhenMoreThan3Parts() { + assertThatThrownBy(() -> UserQuotaThresholds.Id.fromKey("1/2/3/4")).isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void fromKeyShouldThrowWhenPrefixIsNotQuotaThreasholdEvents() { + assertThatThrownBy(() -> UserQuotaThresholds.Id.fromKey("WrongPrefix/bob@domain/name")).isInstanceOf(IllegalArgumentException.class); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java ---------------------------------------------------------------------- diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java index 08ded89..ef5585b 100644 --- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java +++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraJmapTestRule.java @@ -33,10 +33,9 @@ import org.junit.runners.model.Statement; import com.google.inject.Module; - public class CassandraJmapTestRule implements TestRule { - private static final int LIMIT_TO_3_MESSAGES = 3; + private static final int LIMIT_TO_10_MESSAGES = 10; private final TemporaryFolder temporaryFolder; public static CassandraJmapTestRule defaultTestRule() { @@ -65,7 +64,7 @@ public class CassandraJmapTestRule implements TestRule { CassandraJamesServerMain.PROTOCOLS, CassandraJamesServerMain.PLUGINS) .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class)) - .overrideWith(new TestJMAPServerModule(LIMIT_TO_3_MESSAGES)) + .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES)) .overrideWith(new TestESMetricReporterModule()) .overrideWith(guiceModuleTestRule.getModule()) .overrideWith(additionals); http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapTestRule.java ---------------------------------------------------------------------- diff --git a/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapTestRule.java b/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapTestRule.java index 69762f2..b1ac91e 100644 --- a/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapTestRule.java +++ b/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapTestRule.java @@ -38,7 +38,7 @@ import com.google.inject.Module; public class MemoryJmapTestRule implements TestRule { - private static final int LIMIT_TO_3_MESSAGES = 3; + private static final int LIMIT_TO_10_MESSAGES = 10; public TemporaryFolder temporaryFolder = new TemporaryFolder(); @@ -49,11 +49,11 @@ public class MemoryJmapTestRule implements TestRule { .build(); return new GuiceJamesServer(configuration) .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE) - .overrideWith(modules) - .overrideWith(new TestJMAPServerModule(LIMIT_TO_3_MESSAGES)) + .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES)) .overrideWith(binder -> binder.bind(PersistenceAdapter.class).to(MemoryPersistenceAdapter.class)) .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class)) - .overrideWith(binder -> binder.bind(MessageSearchIndex.class).to(SimpleMessageSearchIndex.class)); + .overrideWith(binder -> binder.bind(MessageSearchIndex.class).to(SimpleMessageSearchIndex.class)) + .overrideWith(modules); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraGetMessageListMethodTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraGetMessageListMethodTest.java b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraGetMessageListMethodTest.java index 634da89..ed41abe 100644 --- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraGetMessageListMethodTest.java +++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraGetMessageListMethodTest.java @@ -26,6 +26,7 @@ import org.apache.james.DockerCassandraRule; import org.apache.james.GuiceJamesServer; import org.apache.james.backends.cassandra.ContainerLifecycleConfiguration; import org.apache.james.jmap.methods.integration.GetMessageListMethodTest; +import org.apache.james.modules.TestJMAPServerModule; import org.junit.ClassRule; import org.junit.Rule; import org.junit.rules.TestRule; @@ -45,7 +46,8 @@ public class CassandraGetMessageListMethodTest extends GetMessageListMethodTest @Override protected GuiceJamesServer createJmapServer() throws IOException { - return rule.jmapServer(cassandra.getModule()); + return rule.jmapServer(cassandra.getModule(), + new TestJMAPServerModule(LIMIT_TO_3_MESSAGES)); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml index 8c82680..93fad5f 100644 --- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml +++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/listeners.xml @@ -31,6 +31,16 @@ <thresholds> <threshold>0.1</threshold> </thresholds> + <name>first</name> + </configuration> + </listener> + <listener> + <class>org.apache.james.mailbox.quota.mailing.listeners.QuotaThresholdCrossingListener</class> + <configuration> + <thresholds> + <threshold>0.2</threshold> + </thresholds> + <name>second</name> </configuration> </listener> </listeners> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java index 055d1ce..8780771 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java @@ -79,6 +79,7 @@ import org.junit.Test; import com.jayway.restassured.RestAssured; public abstract class GetMessageListMethodTest { + public static final int LIMIT_TO_3_MESSAGES = 3; private static final String FORWARDED = "$Forwarded"; private static final ZoneId ZONE_ID = ZoneId.of("Europe/Paris"); private ACLProbeImpl aclProbe; http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java index ec5d65a..4753add 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/QuotaMailingTest.java @@ -49,6 +49,7 @@ import org.apache.james.modules.QuotaProbesImpl; import org.apache.james.probe.DataProbe; import org.apache.james.utils.DataProbeImpl; import org.apache.james.utils.JmapGuiceProbe; +import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -88,6 +89,11 @@ public abstract class QuotaMailingTest { bartAccessToken = authenticateJamesUser(baseUri(jmapServer), BART, BOB_PASSWORD); } + @After + public void tearDown() { + jmapServer.stop(); + } + @Test public void shouldSendANoticeWhenThresholdExceeded() throws Exception { jmapServer.getProbe(QuotaProbesImpl.class) @@ -96,6 +102,7 @@ public abstract class QuotaMailingTest { bartSendMessageToHomer(); // Homer receives a mail big enough to trigger a configured threshold + calmlyAwait.atMost(30, TimeUnit.SECONDS) .until(() -> listMessageIdsForAccount(homerAccessToken).size() == 2); @@ -123,11 +130,15 @@ public abstract class QuotaMailingTest { new SerializableQuotaValue<>(QuotaSize.size(100 * 1000))); bartSendMessageToHomer(); - // Home receives a mail big enough to trigger a configured threshold - + // Homer receives a mail big enough to trigger a 10% configured threshold calmlyAwait.atMost(30, TimeUnit.SECONDS) .until(() -> listMessageIdsForAccount(homerAccessToken).size() == 2); + bartSendMessageToHomer(); + // Homer receives a mail big enough to trigger a 20% configured threshold + calmlyAwait.atMost(30, TimeUnit.SECONDS) + .until(() -> listMessageIdsForAccount(homerAccessToken).size() == 4); + List<String> ids = listMessageIdsForAccount(homerAccessToken); String idString = ids.stream() .map(id -> "\"" + id + "\"") @@ -142,7 +153,9 @@ public abstract class QuotaMailingTest { .statusCode(200) .log().ifValidationFails() .body(ARGUMENTS + ".list.textBody", - hasItem(containsString("You currently occupy more than 10 % of the total size allocated to you"))); + hasItem(containsString("You currently occupy more than 10 % of the total size allocated to you"))) + .body(ARGUMENTS + ".list.textBody", + hasItem(containsString("You currently occupy more than 20 % of the total size allocated to you"))); } private void bartSendMessageToHomer() { http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryGetMessageListMethodTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryGetMessageListMethodTest.java b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryGetMessageListMethodTest.java index 79bc15d..23c495e 100644 --- a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryGetMessageListMethodTest.java +++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryGetMessageListMethodTest.java @@ -24,6 +24,7 @@ import java.io.IOException; import org.apache.james.GuiceJamesServer; import org.apache.james.MemoryJmapTestRule; import org.apache.james.jmap.methods.integration.GetMessageListMethodTest; +import org.apache.james.modules.TestJMAPServerModule; import org.junit.Rule; public class MemoryGetMessageListMethodTest extends GetMessageListMethodTest { @@ -33,7 +34,7 @@ public class MemoryGetMessageListMethodTest extends GetMessageListMethodTest { @Override protected GuiceJamesServer createJmapServer() throws IOException { - return memoryJmap.jmapServer(); + return memoryJmap.jmapServer(new TestJMAPServerModule(LIMIT_TO_3_MESSAGES)); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/8e5f2cc2/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml index 47a3381..9d0a0fe 100644 --- a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml +++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/listeners.xml @@ -28,6 +28,16 @@ <thresholds> <threshold>0.1</threshold> </thresholds> + <name>first</name> + </configuration> + </listener> + <listener> + <class>org.apache.james.mailbox.quota.mailing.listeners.QuotaThresholdCrossingListener</class> + <configuration> + <thresholds> + <threshold>0.2</threshold> + </thresholds> + <name>second</name> </configuration> </listener> </listeners> \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
