This is an automated email from the ASF dual-hosted git repository.

chibenwa 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 7bab11c816 [FIX] MOVE/COPY should not exceed batch size in published 
events (sam… (#3047)
7bab11c816 is described below

commit 7bab11c816b4b8df7fc0ac683f39ea0892a528c5
Author: Benoit TELLIER <[email protected]>
AuthorDate: Tue May 26 06:47:47 2026 +0200

    [FIX] MOVE/COPY should not exceed batch size in published events (sam… 
(#3047)
    
    Co-authored-by: Rene Cordier <[email protected]>
---
 .../james/mailbox/store/StoreMessageManager.java   | 167 ++++++++++-----------
 .../james/webadmin/service/RestoreServiceTest.java |  13 +-
 2 files changed, 90 insertions(+), 90 deletions(-)

diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
index 9e5190760d..78e944b79e 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
@@ -52,6 +52,7 @@ import 
org.apache.commons.io.input.UnsynchronizedFilterInputStream;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.events.EventBus;
 import org.apache.james.events.EventListener;
+import org.apache.james.events.RegistrationKey;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxManager.MessageCapabilities;
 import org.apache.james.mailbox.MailboxPathLocker;
@@ -745,49 +746,47 @@ public class StoreMessageManager implements 
MessageManager {
     }
 
     private Mono<SortedMap<MessageUid, MessageMetaData>> 
copyAll(List<MessageRange> sets, StoreMessageManager to, MailboxSession 
session) {
+        MessageMoves messageMoves = MessageMoves.builder()
+            .previousMailboxIds(getMailboxEntity().getMailboxId())
+            .targetMailboxIds(to.getMailboxEntity().getMailboxId(), 
getMailboxEntity().getMailboxId())
+            .build();
+        ImmutableSet<RegistrationKey> registrationKeys = 
messageMoves.impactedMailboxIds()
+            .<RegistrationKey>map(MailboxIdRegistrationKey::new)
+            .collect(ImmutableSet.toImmutableSet());
+
         return Flux.fromIterable(sets)
             .concatMap(set -> retrieveOriginalRows(set, session))
             .window(batchSizes.getCopyBatchSize().orElse(Integer.MAX_VALUE))
             .concatMap(window -> window.collectList()
                 .flatMap(originalRows -> to.copy(originalRows, 
session).collectList()
-                    .map(copyResult -> Pair.of(
-                        collectMetadata(copyResult.iterator()),
-                        originalRows.stream()
+                    .flatMap(copyResult -> {
+                        SortedMap<MessageUid, MessageMetaData> copiedUids = 
collectMetadata(copyResult.iterator());
+                        ImmutableList<MessageId> messageIds = 
originalRows.stream()
                             
.map(org.apache.james.mailbox.store.mail.model.Message::getMessageId)
-                            .collect(ImmutableList.toImmutableList())))))
-            .collectList()
-            .flatMap(allResults -> {
-                if (allResults.isEmpty()) {
-                    return Mono.just(ImmutableSortedMap.of());
-                }
-                SortedMap<MessageUid, MessageMetaData> allCopiedUids = new 
TreeMap<>();
-                List<MessageId> allMessageIds = new ArrayList<>();
-                for (Pair<SortedMap<MessageUid, MessageMetaData>, 
ImmutableList<MessageId>> result : allResults) {
-                    allCopiedUids.putAll(result.getLeft());
-                    allMessageIds.addAll(result.getRight());
-                }
-                MessageMoves messageMoves = MessageMoves.builder()
-                    .previousMailboxIds(getMailboxEntity().getMailboxId())
-                    .targetMailboxIds(to.getMailboxEntity().getMailboxId(), 
getMailboxEntity().getMailboxId())
-                    .build();
-                EventBus.EventWithRegistrationKey added = new 
EventBus.EventWithRegistrationKey(
-                    EventFactory.added()
-                        .randomEventId()
-                        .mailboxSession(session)
-                        .mailbox(to.getMailboxEntity())
-                        .metaData(allCopiedUids)
-                        .isDelivery(!IS_DELIVERY)
-                        .isAppended(!IS_APPENDED)
-                        .build(),
-                    ImmutableSet.of(new 
MailboxIdRegistrationKey(to.getMailboxEntity().getMailboxId())));
-                EventBus.EventWithRegistrationKey moved = new 
EventBus.EventWithRegistrationKey(
-                    EventFactory.moved()
-                        .messageMoves(messageMoves)
-                        .messageId(allMessageIds)
-                        .session(session)
-                        .build(),
-                    
messageMoves.impactedMailboxIds().map(MailboxIdRegistrationKey::new).collect(ImmutableSet.toImmutableSet()));
-                return Mono.from(eventBus.dispatch(ImmutableList.of(added, 
moved))).thenReturn(allCopiedUids);
+                            .collect(ImmutableList.toImmutableList());
+                        EventBus.EventWithRegistrationKey added = new 
EventBus.EventWithRegistrationKey(
+                            EventFactory.added()
+                                .randomEventId()
+                                .mailboxSession(session)
+                                .mailbox(to.getMailboxEntity())
+                                .metaData(copiedUids)
+                                .isDelivery(!IS_DELIVERY)
+                                .isAppended(!IS_APPENDED)
+                                .build(),
+                            ImmutableSet.of(new 
MailboxIdRegistrationKey(to.getMailboxEntity().getMailboxId())));
+                        EventBus.EventWithRegistrationKey moved = new 
EventBus.EventWithRegistrationKey(
+                            EventFactory.moved()
+                                .messageMoves(messageMoves)
+                                .messageId(messageIds)
+                                .session(session)
+                                .build(),
+                            registrationKeys);
+                        return 
Mono.from(eventBus.dispatch(ImmutableList.of(added, moved)))
+                            .thenReturn(copiedUids);
+                    })))
+            .reduce(new TreeMap<>(), (acc, batchUids) -> {
+                acc.putAll(batchUids);
+                return acc;
             });
     }
 
@@ -834,63 +833,55 @@ public class StoreMessageManager implements 
MessageManager {
     }
 
     private Mono<SortedMap<MessageUid, MessageMetaData>> 
moveAll(List<MessageRange> sets, StoreMessageManager to, MailboxSession 
session) {
+        MessageMoves messageMoves = MessageMoves.builder()
+            .previousMailboxIds(getMailboxEntity().getMailboxId())
+            .targetMailboxIds(to.getMailboxEntity().getMailboxId())
+            .build();
+        ImmutableSet<RegistrationKey> registrationKeys = 
messageMoves.impactedMailboxIds()
+            .<RegistrationKey>map(MailboxIdRegistrationKey::new)
+            .collect(ImmutableSet.toImmutableSet());
+
         return Flux.fromIterable(sets)
             .concatMap(set -> retrieveOriginalRows(set, session))
             .window(batchSizes.getCopyBatchSize().orElse(Integer.MAX_VALUE))
             .concatMap(window -> window
                 .collectList()
                 .flatMap(originalRows -> to.move(originalRows, session)
-                    .map(moveResult -> Pair.of(moveResult, originalRows))))
-            .collectList()
-            .flatMap(allResults -> {
-                if (allResults.isEmpty()) {
-                    return Mono.just(ImmutableSortedMap.of());
-                }
-
-                SortedMap<MessageUid, MessageMetaData> allMoveUids = new 
TreeMap<>();
-                List<MessageMetaData> allOriginalMessages = new ArrayList<>();
-                List<MessageId> allMessageIds = new ArrayList<>();
-
-                for (Pair<MoveResult, List<MailboxMessage>> result : 
allResults) {
-                    
allMoveUids.putAll(collectMetadata(result.getLeft().getMovedMessages().iterator()));
-                    
allOriginalMessages.addAll(result.getLeft().getOriginalMessages());
-                    result.getRight().stream()
-                        
.map(org.apache.james.mailbox.store.mail.model.Message::getMessageId)
-                        .forEach(allMessageIds::add);
-                }
-
-                MessageMoves messageMoves = MessageMoves.builder()
-                    .previousMailboxIds(getMailboxEntity().getMailboxId())
-                    .targetMailboxIds(to.getMailboxEntity().getMailboxId())
-                    .build();
-
-                EventBus.EventWithRegistrationKey added = new 
EventBus.EventWithRegistrationKey(EventFactory.added()
-                    .randomEventId()
-                    .mailboxSession(session)
-                    .mailbox(to.getMailboxEntity())
-                    .metaData(allMoveUids)
-                    .isDelivery(!IS_DELIVERY)
-                    .isAppended(!IS_APPENDED)
-                    .movedFrom(getId())
-                    .build(),
-                    ImmutableSet.of(new 
MailboxIdRegistrationKey(to.getMailboxEntity().getMailboxId())));
-                EventBus.EventWithRegistrationKey expunged = new 
EventBus.EventWithRegistrationKey(EventFactory.expunged()
-                    .randomEventId()
-                    .mailboxSession(session)
-                    .mailbox(getMailboxEntity())
-                    .addMetaData(allOriginalMessages)
-                    .movedTo(to.getId())
-                    .build(),
-                    ImmutableSet.of(new 
MailboxIdRegistrationKey(mailbox.getMailboxId())));
-                EventBus.EventWithRegistrationKey moved = new 
EventBus.EventWithRegistrationKey(EventFactory.moved()
-                    .messageMoves(messageMoves)
-                    .messageId(allMessageIds)
-                    .session(session)
-                    .build(),
-                    
messageMoves.impactedMailboxIds().map(MailboxIdRegistrationKey::new).collect(ImmutableSet.toImmutableSet()));
-
-                return Mono.from(eventBus.dispatch(ImmutableList.of(added, 
expunged, moved)))
-                    .thenReturn(allMoveUids);
+                    .flatMap(moveResult -> {
+                        SortedMap<MessageUid, MessageMetaData> moveUids = 
collectMetadata(moveResult.getMovedMessages().iterator());
+                        ImmutableList<MessageId> messageIds = 
originalRows.stream()
+                            
.map(org.apache.james.mailbox.store.mail.model.Message::getMessageId)
+                            .collect(ImmutableList.toImmutableList());
+                        EventBus.EventWithRegistrationKey added = new 
EventBus.EventWithRegistrationKey(EventFactory.added()
+                            .randomEventId()
+                            .mailboxSession(session)
+                            .mailbox(to.getMailboxEntity())
+                            .metaData(moveUids)
+                            .isDelivery(!IS_DELIVERY)
+                            .isAppended(!IS_APPENDED)
+                            .movedFrom(getId())
+                            .build(),
+                            ImmutableSet.of(new 
MailboxIdRegistrationKey(to.getMailboxEntity().getMailboxId())));
+                        EventBus.EventWithRegistrationKey expunged = new 
EventBus.EventWithRegistrationKey(EventFactory.expunged()
+                            .randomEventId()
+                            .mailboxSession(session)
+                            .mailbox(getMailboxEntity())
+                            .addMetaData(moveResult.getOriginalMessages())
+                            .movedTo(to.getId())
+                            .build(),
+                            ImmutableSet.of(new 
MailboxIdRegistrationKey(mailbox.getMailboxId())));
+                        EventBus.EventWithRegistrationKey moved = new 
EventBus.EventWithRegistrationKey(EventFactory.moved()
+                            .messageMoves(messageMoves)
+                            .messageId(messageIds)
+                            .session(session)
+                            .build(),
+                            registrationKeys);
+                        return 
Mono.from(eventBus.dispatch(ImmutableList.of(added, expunged, moved)))
+                            .thenReturn(moveUids);
+                    })))
+            .reduce(new TreeMap<>(), (acc, batchUids) -> {
+                acc.putAll(batchUids);
+                return acc;
             });
     }
 
diff --git 
a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/RestoreServiceTest.java
 
b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/RestoreServiceTest.java
index 5eab10a74e..121d78d75d 100644
--- 
a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/RestoreServiceTest.java
+++ 
b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/service/RestoreServiceTest.java
@@ -24,6 +24,8 @@ import static 
org.apache.james.webadmin.service.ExportServiceTestSystem.BOB;
 import static org.apache.james.webadmin.service.ExportServiceTestSystem.CEDRIC;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.awaitility.Durations.FIVE_HUNDRED_MILLISECONDS;
+import static org.awaitility.Durations.ONE_MINUTE;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doThrow;
 
@@ -49,6 +51,8 @@ import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageResultIterator;
 import org.apache.james.task.Task;
 import org.assertj.core.api.SoftAssertions;
+import org.awaitility.Awaitility;
+import org.awaitility.core.ConditionFactory;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -65,6 +69,10 @@ class RestoreServiceTest {
         "Content-Type: text/plain; charset=UTF-8\r\n" +
         "\r\n" +
         "testmail";
+    private static final ConditionFactory AWAIT = Awaitility.await()
+        .atMost(ONE_MINUTE)
+        .with()
+        .pollInterval(FIVE_HUNDRED_MILLISECONDS);
 
     private RestoreService testee;
     private ExportServiceTestSystem testSystem;
@@ -300,8 +308,9 @@ class RestoreServiceTest {
 
         testee.restore(CEDRIC, blobId).block();
 
-        assertThatThrownBy(() -> 
testSystem.blobStore.read(testSystem.blobStore.getDefaultBucketName(), blobId))
-            .isInstanceOf(ObjectNotFoundException.class);
+        AWAIT.untilAsserted(() ->
+            assertThatThrownBy(() -> 
testSystem.blobStore.read(testSystem.blobStore.getDefaultBucketName(), blobId))
+                .isInstanceOf(ObjectNotFoundException.class));
     }
 
     private ComposedMessageId createAMailboxWithAMail() throws 
MailboxException {


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

Reply via email to