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

Arsnael 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 0484f24c12 [FIX] MessageManager::setFlags should support overlapping 
ranges
0484f24c12 is described below

commit 0484f24c12c4821d9e98f822e065187b3b3abbbb
Author: Benoit TELLIER <[email protected]>
AuthorDate: Sun Jul 5 21:43:40 2026 +0200

    [FIX] MessageManager::setFlags should support overlapping ranges
---
 .../apache/james/mailbox/MailboxManagerTest.java   | 23 ++++++++++++++++++++++
 .../james/mailbox/store/StoreMessageManager.java   | 10 +++++++++-
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git 
a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java 
b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java
index c3253f44ef..095108596a 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java
@@ -36,6 +36,7 @@ import static org.mockito.Mockito.when;
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
@@ -1086,6 +1087,28 @@ public abstract class MailboxManagerTest<T extends 
MailboxManager> {
                 .satisfies(event -> assertThat(event.getUids()).hasSize(1));
         }
 
+        @Test
+        void setFlagsReactiveShouldSupportOverlappingRanges() throws Exception 
{
+            
inboxManager.appendMessage(MessageManager.AppendCommand.builder().build(message),
 session);
+            
inboxManager.appendMessage(MessageManager.AppendCommand.builder().build(message),
 session);
+
+            Mono.from(retrieveEventBus(mailboxManager).register(listener, new 
MailboxIdRegistrationKey(inboxId))).block();
+
+            // Clients may supply overlapping ranges (eg. STORE 1:5,3:7), in 
which case the same UID
+            // is updated several times. This must not fail nor produce 
duplicated entries. See JAMES issue #5570.
+            Map<MessageUid, Flags> result = 
Mono.from(inboxManager.setFlagsReactive(
+                new Flags(Flags.Flag.SEEN), MessageManager.FlagsUpdateMode.ADD,
+                List.of(MessageRange.all(), MessageRange.all()), 
session)).block();
+
+            assertThat(result).hasSize(2);
+            assertThat(listener.getEvents())
+                .filteredOn(event -> event instanceof FlagsUpdated)
+                .hasSize(1)
+                .extracting(event -> (FlagsUpdated) event)
+                .element(0)
+                .satisfies(event -> assertThat(event.getUids()).hasSize(2));
+        }
+
         @Test
         void moveShouldFireAddedEventInTargetMailbox() throws Exception {
             assumeTrue(mailboxManager.hasCapability(MailboxCapabilities.Move));
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 78e944b79e..6cf0c8caf1 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
@@ -698,9 +698,17 @@ public class StoreMessageManager implements MessageManager 
{
                     .concatMap(set -> 
messageMapper.executeReactive(messageMapper.updateFlagsReactive(getMailboxEntity(),
 calculator, set)))
                     .collectList()
                     .flatMap(allUpdatedFlagsPerRange -> {
+                        // Ranges supplied by the client may overlap (eg. 
STORE 1:5,3:7), in which case the same
+                        // UID is updated several times. Deduplicate by UID 
(keeping the first, meaningful update)
+                        // so that neither the dispatched event nor the 
returned map contain conflicting entries.
                         ImmutableList<UpdatedFlags> allUpdatedFlags = 
allUpdatedFlagsPerRange.stream()
                             .flatMap(List::stream)
-                            .collect(ImmutableList.toImmutableList());
+                            .collect(ImmutableMap.toImmutableMap(
+                                UpdatedFlags::getUid,
+                                Function.identity(),
+                                (first, second) -> first))
+                            .values()
+                            .asList();
                         return eventBus.dispatch(EventFactory.flagsUpdated()
                                     .randomEventId()
                                     .mailboxSession(mailboxSession)


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

Reply via email to