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


The following commit(s) were added to refs/heads/master by this push:
     new ef0a66c564 JAMES-4094 Trigger quota-ratio index update when modifying 
quota limits (#2538)
ef0a66c564 is described below

commit ef0a66c5646663e86178f4995f9098b1633c00a8
Author: Benoit TELLIER <[email protected]>
AuthorDate: Tue Dec 3 15:27:21 2024 +0100

    JAMES-4094 Trigger quota-ratio index update when modifying quota limits 
(#2538)
    
    Co-authored-by: Rene Cordier <[email protected]>
---
 .../james/mailbox/quota/QuotaChangeNotifier.java   | 51 ++++++++++++
 .../quota/CassandraPerUserMaxQuotaManagerV2.java   | 41 ++++++---
 .../cassandra/CassandraMailboxManagerProvider.java |  3 +-
 .../cassandra/CassandraTestSystemFixture.java      |  3 +-
 ...ssandraPerUserMaxQuotaManagerMigrationTest.java |  5 +-
 .../CassandraPerUserMaxQuotaManagerV2Test.java     |  7 +-
 .../store/quota/DefaultQuotaChangeNotifier.java    | 96 ++++++++++++++++++++++
 .../cassandra/host/CassandraHostSystem.java        |  3 +-
 .../mailbox/CassandraMailboxQuotaLegacyModule.java |  8 ++
 .../mailbox/CassandraMailboxQuotaModule.java       |  8 ++
 .../mailbox/UsersRepositoryUsernameSupplier.java   | 42 ++++++++++
 11 files changed, 247 insertions(+), 20 deletions(-)

diff --git 
a/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaChangeNotifier.java
 
b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaChangeNotifier.java
new file mode 100644
index 0000000000..b9f05c9276
--- /dev/null
+++ 
b/mailbox/api/src/main/java/org/apache/james/mailbox/quota/QuotaChangeNotifier.java
@@ -0,0 +1,51 @@
+/****************************************************************
+ * 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;
+
+import org.apache.james.core.Domain;
+import org.apache.james.mailbox.model.QuotaRoot;
+import org.reactivestreams.Publisher;
+
+import reactor.core.publisher.Mono;
+
+public interface QuotaChangeNotifier {
+    QuotaChangeNotifier NOOP = new QuotaChangeNotifier() {
+        @Override
+        public Publisher<Void> notifyUpdate(QuotaRoot quotaRoot) {
+            return Mono.empty();
+        }
+
+        @Override
+        public Publisher<Void> notifyUpdate(Domain domain) {
+            return Mono.empty();
+        }
+
+        @Override
+        public Publisher<Void> notifyGlobalUpdate() {
+            return Mono.empty();
+        }
+    };
+
+    Publisher<Void> notifyUpdate(QuotaRoot quotaRoot);
+
+    Publisher<Void> notifyUpdate(Domain domain);
+
+    Publisher<Void> notifyGlobalUpdate();
+}
diff --git 
a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerV2.java
 
b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerV2.java
index e310aa9343..0895b24c68 100644
--- 
a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerV2.java
+++ 
b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerV2.java
@@ -42,6 +42,7 @@ import org.apache.james.core.quota.QuotaType;
 import org.apache.james.mailbox.model.Quota;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.mailbox.quota.QuotaChangeNotifier;
 
 import com.google.common.collect.ImmutableMap;
 
@@ -53,10 +54,12 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
     private static final String GLOBAL_IDENTIFIER = "global";
 
     private final CassandraQuotaLimitDao cassandraQuotaLimitDao;
+    private final QuotaChangeNotifier quotaChangeNotifier;
 
     @Inject
-    public CassandraPerUserMaxQuotaManagerV2(CassandraQuotaLimitDao 
cassandraQuotaLimitDao) {
+    public CassandraPerUserMaxQuotaManagerV2(CassandraQuotaLimitDao 
cassandraQuotaLimitDao, QuotaChangeNotifier quotaChangeNotifier) {
         this.cassandraQuotaLimitDao = cassandraQuotaLimitDao;
+        this.quotaChangeNotifier = quotaChangeNotifier;
     }
 
     @Override
@@ -72,7 +75,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
                 .quotaComponent(QuotaComponent.MAILBOX)
                 .quotaType(QuotaType.SIZE)
                 .quotaLimit(QuotaCodec.quotaValueToLong(maxStorageQuota))
-                .build());
+                .build())
+            .then(Mono.from(quotaChangeNotifier.notifyUpdate(quotaRoot)));
     }
 
     @Override
@@ -88,7 +92,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
                 .quotaComponent(QuotaComponent.MAILBOX)
                 .quotaType(QuotaType.COUNT)
                 .quotaLimit(QuotaCodec.quotaValueToLong(maxMessageCount))
-                .build());
+                .build())
+            .then(Mono.from(quotaChangeNotifier.notifyUpdate(quotaRoot)));
     }
 
     @Override
@@ -104,7 +109,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
                 .quotaComponent(QuotaComponent.MAILBOX)
                 .quotaType(QuotaType.COUNT)
                 .quotaLimit(QuotaCodec.quotaValueToLong(count))
-                .build());
+                .build())
+            .then(Mono.from(quotaChangeNotifier.notifyUpdate(domain)));
     }
 
     @Override
@@ -120,7 +126,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
                 .quotaComponent(QuotaComponent.MAILBOX)
                 .quotaType(QuotaType.SIZE)
                 .quotaLimit(QuotaCodec.quotaValueToLong(size))
-                .build());
+                .build())
+            .then(Mono.from(quotaChangeNotifier.notifyUpdate(domain)));
     }
 
     @Override
@@ -130,7 +137,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
 
     @Override
     public Mono<Void> removeDomainMaxMessageReactive(Domain domain) {
-        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.DOMAIN, domain.asString(), QuotaType.COUNT));
+        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.DOMAIN, domain.asString(), QuotaType.COUNT))
+            .then(Mono.from(quotaChangeNotifier.notifyUpdate(domain)));
     }
 
     @Override
@@ -140,7 +148,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
 
     @Override
     public Mono<Void> removeDomainMaxStorageReactive(Domain domain) {
-        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.DOMAIN, domain.asString(), QuotaType.SIZE));
+        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.DOMAIN, domain.asString(), QuotaType.SIZE))
+            .then(Mono.from(quotaChangeNotifier.notifyUpdate(domain)));
     }
 
     @Override
@@ -170,7 +179,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
 
     @Override
     public Mono<Void> removeMaxMessageReactive(QuotaRoot quotaRoot) {
-        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.USER, quotaRoot.getValue(), QuotaType.COUNT));
+        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.USER, quotaRoot.getValue(), QuotaType.COUNT))
+            .then(Mono.from(quotaChangeNotifier.notifyUpdate(quotaRoot)));
     }
 
     @Override
@@ -180,7 +190,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
 
     @Override
     public Mono<Void> removeMaxStorageReactive(QuotaRoot quotaRoot) {
-        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.USER, quotaRoot.getValue(), QuotaType.SIZE));
+        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.USER, quotaRoot.getValue(), QuotaType.SIZE))
+            .then(Mono.from(quotaChangeNotifier.notifyUpdate(quotaRoot)));
     }
 
     @Override
@@ -195,7 +206,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
                 .quotaComponent(QuotaComponent.MAILBOX)
                 .quotaType(QuotaType.SIZE)
                 .quotaLimit(QuotaCodec.quotaValueToLong(globalMaxStorage))
-                .build());
+                .build())
+            .then(Mono.from(quotaChangeNotifier.notifyGlobalUpdate()));
     }
 
     @Override
@@ -205,7 +217,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
 
     @Override
     public Mono<Void> removeGlobalMaxStorageReactive() {
-        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.GLOBAL, GLOBAL_IDENTIFIER, QuotaType.SIZE));
+        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.GLOBAL, GLOBAL_IDENTIFIER, QuotaType.SIZE))
+            .then(Mono.from(quotaChangeNotifier.notifyGlobalUpdate()));
     }
 
     @Override
@@ -220,7 +233,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
                 .quotaComponent(QuotaComponent.MAILBOX)
                 .quotaType(QuotaType.COUNT)
                 .quotaLimit(QuotaCodec.quotaValueToLong(globalMaxMessageCount))
-                .build());
+                .build())
+            .then(Mono.from(quotaChangeNotifier.notifyGlobalUpdate()));
     }
 
     @Override
@@ -230,7 +244,8 @@ public class CassandraPerUserMaxQuotaManagerV2 implements 
MaxQuotaManager {
 
     @Override
     public Mono<Void> removeGlobalMaxMessageReactive() {
-        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.GLOBAL, GLOBAL_IDENTIFIER, QuotaType.COUNT));
+        return 
cassandraQuotaLimitDao.deleteQuotaLimit(QuotaLimitKey.of(QuotaComponent.MAILBOX,
 QuotaScope.GLOBAL, GLOBAL_IDENTIFIER, QuotaType.COUNT))
+            .then(Mono.from(quotaChangeNotifier.notifyGlobalUpdate()));
     }
 
     @Override
diff --git 
a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java
 
b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java
index 0d7b7a1656..cbdf9bfb2e 100644
--- 
a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java
+++ 
b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java
@@ -40,6 +40,7 @@ import 
org.apache.james.mailbox.cassandra.quota.CassandraCurrentQuotaManagerV2;
 import 
org.apache.james.mailbox.cassandra.quota.CassandraPerUserMaxQuotaManagerV2;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.mailbox.quota.QuotaChangeNotifier;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.store.MailboxManagerConfiguration;
 import org.apache.james.mailbox.store.NoMailboxPathLocker;
@@ -115,7 +116,7 @@ public class CassandraMailboxManagerProvider {
             LIMIT_ANNOTATIONS, LIMIT_ANNOTATION_SIZE);
 
         SessionProviderImpl sessionProvider = new 
SessionProviderImpl(noAuthenticator, noAuthorizator);
-        MaxQuotaManager maxQuotaManager = new 
CassandraPerUserMaxQuotaManagerV2(new CassandraQuotaLimitDao(session));
+        MaxQuotaManager maxQuotaManager = new 
CassandraPerUserMaxQuotaManagerV2(new CassandraQuotaLimitDao(session), 
QuotaChangeNotifier.NOOP);
         CassandraCurrentQuotaManagerV2 currentQuotaUpdater = new 
CassandraCurrentQuotaManagerV2(new CassandraQuotaCurrentValueDao(session));
         StoreQuotaManager storeQuotaManager = new 
StoreQuotaManager(currentQuotaUpdater, maxQuotaManager);
         QuotaRootResolver quotaRootResolver = new 
DefaultUserQuotaRootResolver(sessionProvider, mapperFactory);
diff --git 
a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java
 
b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java
index c3d6cec4ca..a843ec7daf 100644
--- 
a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java
+++ 
b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java
@@ -40,6 +40,7 @@ import 
org.apache.james.mailbox.cassandra.quota.CassandraCurrentQuotaManagerV2;
 import 
org.apache.james.mailbox.cassandra.quota.CassandraPerUserMaxQuotaManagerV2;
 import org.apache.james.mailbox.quota.CurrentQuotaManager;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.mailbox.quota.QuotaChangeNotifier;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.store.MailboxManagerConfiguration;
 import org.apache.james.mailbox.store.NoMailboxPathLocker;
@@ -101,7 +102,7 @@ public class CassandraTestSystemFixture {
     }
 
     static MaxQuotaManager createMaxQuotaManager(CassandraCluster cassandra) {
-        return new CassandraPerUserMaxQuotaManagerV2(new 
CassandraQuotaLimitDao(cassandra.getConf()));
+        return new CassandraPerUserMaxQuotaManagerV2(new 
CassandraQuotaLimitDao(cassandra.getConf()), QuotaChangeNotifier.NOOP);
     }
 
     public static CurrentQuotaManager 
createCurrentQuotaManager(CassandraCluster cassandra) {
diff --git 
a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerMigrationTest.java
 
b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerMigrationTest.java
index 69c27a59ce..aebc8e973a 100644
--- 
a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerMigrationTest.java
+++ 
b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerMigrationTest.java
@@ -26,6 +26,7 @@ import java.util.Optional;
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import 
org.apache.james.backends.cassandra.components.CassandraMutualizedQuotaModule;
+import org.apache.james.backends.cassandra.components.CassandraQuotaLimitDao;
 import org.apache.james.core.Domain;
 import org.apache.james.core.Username;
 import org.apache.james.core.quota.QuotaCountLimit;
@@ -37,6 +38,7 @@ import 
org.apache.james.mailbox.cassandra.modules.CassandraMailboxQuotaModule;
 import 
org.apache.james.mailbox.cassandra.quota.migration.CassandraPerUserMaxQuotaManagerMigration;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.mailbox.quota.QuotaChangeNotifier;
 import org.apache.james.mailbox.quota.UserQuotaRootResolver;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.cassandra.CassandraUsersDAO;
@@ -74,7 +76,8 @@ public class CassandraPerUserMaxQuotaManagerMigrationTest {
         usersRepository = new UsersRepositoryImpl<>(domainList, usersDAO);
         Injector testInjector = 
GuiceUtils.testInjector(cassandraCluster.getCassandraCluster());
         oldMaxQuotaManager = 
testInjector.getInstance(CassandraPerUserMaxQuotaManagerV1.class);
-        newMaxQuotaManager = 
testInjector.getInstance(CassandraPerUserMaxQuotaManagerV2.class);
+        newMaxQuotaManager = new CassandraPerUserMaxQuotaManagerV2(new 
CassandraQuotaLimitDao(cassandraCluster.getCassandraCluster().getConf()),
+            QuotaChangeNotifier.NOOP);
         UserQuotaRootResolver userQuotaRootResolver = 
Mockito.mock(UserQuotaRootResolver.class);
         
Mockito.when(userQuotaRootResolver.forUser(USERNAME)).thenReturn(QUOTA_ROOT);
         migration = new 
CassandraPerUserMaxQuotaManagerMigration(usersRepository,
diff --git 
a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerV2Test.java
 
b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerV2Test.java
index bf4bd9e347..fba27d03f7 100644
--- 
a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerV2Test.java
+++ 
b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraPerUserMaxQuotaManagerV2Test.java
@@ -26,9 +26,10 @@ import 
org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.StatementRecorder;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import 
org.apache.james.backends.cassandra.components.CassandraMutualizedQuotaModule;
-import org.apache.james.mailbox.cassandra.mail.utils.GuiceUtils;
+import org.apache.james.backends.cassandra.components.CassandraQuotaLimitDao;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxQuotaModule;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.mailbox.quota.QuotaChangeNotifier;
 import org.apache.james.mailbox.store.quota.GenericMaxQuotaManagerTest;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
@@ -42,8 +43,8 @@ public class CassandraPerUserMaxQuotaManagerV2Test extends 
GenericMaxQuotaManage
 
     @Override
     protected MaxQuotaManager provideMaxQuotaManager() {
-        return GuiceUtils.testInjector(cassandraCluster.getCassandraCluster())
-            .getInstance(CassandraPerUserMaxQuotaManagerV2.class);
+        return new CassandraPerUserMaxQuotaManagerV2(new 
CassandraQuotaLimitDao(cassandraCluster.getCassandraCluster().getConf()),
+            QuotaChangeNotifier.NOOP);
     }
 
     @Test
diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultQuotaChangeNotifier.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultQuotaChangeNotifier.java
new file mode 100644
index 0000000000..6bfef87b0a
--- /dev/null
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultQuotaChangeNotifier.java
@@ -0,0 +1,96 @@
+/****************************************************************
+ * 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.store.quota;
+
+import java.time.Instant;
+import java.util.function.Supplier;
+
+import jakarta.inject.Inject;
+
+import org.apache.james.core.Domain;
+import org.apache.james.core.Username;
+import org.apache.james.events.EventBus;
+import org.apache.james.events.RegistrationKey;
+import org.apache.james.mailbox.model.QuotaRoot;
+import org.apache.james.mailbox.quota.QuotaChangeNotifier;
+import org.apache.james.mailbox.quota.QuotaManager;
+import org.apache.james.mailbox.store.event.EventFactory;
+import org.reactivestreams.Publisher;
+
+import com.google.common.collect.ImmutableSet;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class DefaultQuotaChangeNotifier implements QuotaChangeNotifier {
+    @FunctionalInterface
+    public interface UsernameSupplier extends Supplier<Flux<Username>> {
+
+    }
+
+    private static final ImmutableSet<RegistrationKey> NO_REGISTRATION_KEYS = 
ImmutableSet.of();
+
+    private final UsernameSupplier usernameSupplier;
+    private final DefaultUserQuotaRootResolver quotaRootResolver;
+    private final EventBus eventBus;
+    private final QuotaManager quotaManager;
+
+    @Inject
+    public DefaultQuotaChangeNotifier(UsernameSupplier usernameSupplier, 
DefaultUserQuotaRootResolver quotaRootResolver,
+                                      EventBus eventBus, QuotaManager 
quotaManager) {
+        this.usernameSupplier = usernameSupplier;
+        this.quotaRootResolver = quotaRootResolver;
+        this.eventBus = eventBus;
+        this.quotaManager = quotaManager;
+    }
+
+    @Override
+    public Publisher<Void> notifyUpdate(QuotaRoot quotaRoot) {
+        Username username = quotaRootResolver.associatedUsername(quotaRoot);
+        return Mono.from(quotaManager.getQuotasReactive(quotaRoot))
+            .flatMap(quotas -> eventBus.dispatch(
+                EventFactory.quotaUpdated()
+                    .randomEventId()
+                    .user(username)
+                    .quotaRoot(quotaRoot)
+                    .quotaCount(quotas.getMessageQuota())
+                    .quotaSize(quotas.getStorageQuota())
+                    .instant(Instant.now())
+                    .build(),
+                NO_REGISTRATION_KEYS));
+    }
+
+    @Override
+    public Publisher<Void> notifyUpdate(Domain domain) {
+        return usernameSupplier.get()
+            .map(quotaRootResolver::forUser)
+            .filter(user -> user.getDomain().map(domain::equals).orElse(false))
+            .concatMap(this::notifyUpdate)
+            .then();
+    }
+
+    @Override
+    public Publisher<Void> notifyGlobalUpdate() {
+        return usernameSupplier.get()
+            .map(quotaRootResolver::forUser)
+            .concatMap(this::notifyUpdate)
+            .then();
+    }
+}
diff --git 
a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
 
b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
index bfe1747634..7f766fc2b0 100644
--- 
a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
+++ 
b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
@@ -41,6 +41,7 @@ import 
org.apache.james.mailbox.cassandra.TestCassandraMailboxSessionMapperFacto
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.quota.CassandraCurrentQuotaManagerV2;
 import 
org.apache.james.mailbox.cassandra.quota.CassandraPerUserMaxQuotaManagerV2;
+import org.apache.james.mailbox.quota.QuotaChangeNotifier;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.store.JVMMailboxPathLocker;
 import org.apache.james.mailbox.store.MailboxManagerConfiguration;
@@ -109,7 +110,7 @@ public class CassandraHostSystem extends 
JamesImapHostSystem {
         SessionProviderImpl sessionProvider = new 
SessionProviderImpl(authenticator, authorizator);
         QuotaRootResolver quotaRootResolver = new 
DefaultUserQuotaRootResolver(sessionProvider, mapperFactory);
 
-        perUserMaxQuotaManager = new CassandraPerUserMaxQuotaManagerV2(new 
CassandraQuotaLimitDao(session));
+        perUserMaxQuotaManager = new CassandraPerUserMaxQuotaManagerV2(new 
CassandraQuotaLimitDao(session), QuotaChangeNotifier.NOOP);
         CassandraCurrentQuotaManagerV2 currentQuotaManager = new 
CassandraCurrentQuotaManagerV2(new CassandraQuotaCurrentValueDao(session));
         StoreQuotaManager quotaManager = new 
StoreQuotaManager(currentQuotaManager, perUserMaxQuotaManager);
         ListeningCurrentQuotaUpdater quotaUpdater = new 
ListeningCurrentQuotaUpdater(currentQuotaManager, quotaRootResolver, eventBus, 
quotaManager);
diff --git 
a/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxQuotaLegacyModule.java
 
b/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxQuotaLegacyModule.java
index 1db5fac742..a695e2a3a2 100644
--- 
a/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxQuotaLegacyModule.java
+++ 
b/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxQuotaLegacyModule.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.modules.mailbox;
 
+import org.apache.james.adapter.mailbox.UsersRepositoryUsernameSupplier;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.mailbox.cassandra.quota.CassandraCurrentQuotaManagerV1;
 import org.apache.james.mailbox.cassandra.quota.CassandraCurrentQuotaManagerV2;
@@ -26,6 +27,8 @@ import 
org.apache.james.mailbox.cassandra.quota.CassandraPerUserMaxQuotaManagerV
 import 
org.apache.james.mailbox.cassandra.quota.CassandraPerUserMaxQuotaManagerV2;
 import org.apache.james.mailbox.quota.CurrentQuotaManager;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.mailbox.quota.QuotaChangeNotifier;
+import org.apache.james.mailbox.store.quota.DefaultQuotaChangeNotifier;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Scopes;
@@ -48,6 +51,11 @@ public class CassandraMailboxQuotaLegacyModule extends 
AbstractModule {
         
bind(MaxQuotaManager.class).annotatedWith(Names.named("old")).to(CassandraPerUserMaxQuotaManagerV1.class);
         
bind(MaxQuotaManager.class).annotatedWith(Names.named("new")).to(CassandraPerUserMaxQuotaManagerV2.class);
 
+        bind(UsersRepositoryUsernameSupplier.class).in(Scopes.SINGLETON);
+        bind(DefaultQuotaChangeNotifier.class).in(Scopes.SINGLETON);
+        bind(QuotaChangeNotifier.class).to(DefaultQuotaChangeNotifier.class);
+        
bind(DefaultQuotaChangeNotifier.UsernameSupplier.class).to(UsersRepositoryUsernameSupplier.class);
+
         Multibinder<CassandraModule> cassandraDataDefinitions = 
Multibinder.newSetBinder(binder(), CassandraModule.class);
         
cassandraDataDefinitions.addBinding().toInstance(org.apache.james.mailbox.cassandra.modules.CassandraMailboxQuotaModule.MODULE);
     }
diff --git 
a/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxQuotaModule.java
 
b/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxQuotaModule.java
index 26c11ed178..4d86657fb9 100644
--- 
a/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxQuotaModule.java
+++ 
b/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxQuotaModule.java
@@ -19,12 +19,15 @@
 
 package org.apache.james.modules.mailbox;
 
+import org.apache.james.adapter.mailbox.UsersRepositoryUsernameSupplier;
 import org.apache.james.mailbox.cassandra.quota.CassandraCurrentQuotaManagerV2;
 import 
org.apache.james.mailbox.cassandra.quota.CassandraPerUserMaxQuotaManagerV2;
 import 
org.apache.james.mailbox.cassandra.quota.FakeCassandraCurrentQuotaManager;
 import org.apache.james.mailbox.cassandra.quota.FakeMaxQuotaManager;
 import org.apache.james.mailbox.quota.CurrentQuotaManager;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.mailbox.quota.QuotaChangeNotifier;
+import org.apache.james.mailbox.store.quota.DefaultQuotaChangeNotifier;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Scopes;
@@ -42,5 +45,10 @@ public class CassandraMailboxQuotaModule extends 
AbstractModule {
         
bind(MaxQuotaManager.class).to(CassandraPerUserMaxQuotaManagerV2.class);
         
bind(MaxQuotaManager.class).annotatedWith(Names.named("old")).to(FakeMaxQuotaManager.class);
         
bind(MaxQuotaManager.class).annotatedWith(Names.named("new")).to(CassandraPerUserMaxQuotaManagerV2.class);
+
+        bind(UsersRepositoryUsernameSupplier.class).in(Scopes.SINGLETON);
+        bind(DefaultQuotaChangeNotifier.class).in(Scopes.SINGLETON);
+        bind(QuotaChangeNotifier.class).to(DefaultQuotaChangeNotifier.class);
+        
bind(DefaultQuotaChangeNotifier.UsernameSupplier.class).to(UsersRepositoryUsernameSupplier.class);
     }
 }
diff --git 
a/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/UsersRepositoryUsernameSupplier.java
 
b/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/UsersRepositoryUsernameSupplier.java
new file mode 100644
index 0000000000..08b60ba398
--- /dev/null
+++ 
b/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/UsersRepositoryUsernameSupplier.java
@@ -0,0 +1,42 @@
+/****************************************************************
+ * 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.adapter.mailbox;
+
+import jakarta.inject.Inject;
+
+import org.apache.james.core.Username;
+import org.apache.james.mailbox.store.quota.DefaultQuotaChangeNotifier;
+import org.apache.james.user.api.UsersRepository;
+
+import reactor.core.publisher.Flux;
+
+public class UsersRepositoryUsernameSupplier implements 
DefaultQuotaChangeNotifier.UsernameSupplier {
+    private final UsersRepository usersRepository;
+
+    @Inject
+    public UsersRepositoryUsernameSupplier(UsersRepository usersRepository) {
+        this.usersRepository = usersRepository;
+    }
+
+    @Override
+    public Flux<Username> get() {
+        return Flux.from(usersRepository.listReactive());
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to