This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch 3.9.x in repository https://gitbox.apache.org/repos/asf/james-project.git
commit c163c2c7f6f64d1c4729455a2c6dbcd48636ed25 Author: Benoit TELLIER <[email protected]> AuthorDate: Mon Nov 10 11:46:56 2025 +0100 JAMES-3728 Plug MessageIdManager::updateEmail into the JMAP layer (Email/set update) --- .../jmap/method/EmailSetUpdatePerformer.scala | 31 +++++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetUpdatePerformer.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetUpdatePerformer.scala index 484e2f3fb2..a4d0c21df8 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetUpdatePerformer.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetUpdatePerformer.scala @@ -207,13 +207,30 @@ class EmailSetUpdatePerformer @Inject() (serializer: EmailSetSerializer, if (mailboxIds.value.isEmpty) { SMono.just[EmailUpdateResult](EmailUpdateFailure(EmailSet.asUnparsed(messageId), MessageNotFoundException(messageId))) } else { - updateFlags(messageId, update, mailboxIds, storedMetaData, session) - .flatMap { - case failure: EmailUpdateFailure => SMono.just[EmailUpdateResult](failure) - case _: EmailUpdateSuccess => updateMailboxIds(messageId, update, mailboxIds, session) - } - .onErrorResume(e => SMono.just[EmailUpdateResult](EmailUpdateFailure(EmailSet.asUnparsed(messageId), e))) - .switchIfEmpty(SMono.just[EmailUpdateResult](EmailUpdateSuccess(messageId))) + if (update.update.isMailboxUpdate && update.update.isFlagUpdate) { + // JAMS-3728 Handling move nd flags update at once prevents data race + val targetIds = update.mailboxIdsTransformation.apply(mailboxIds) + val originalFlags: Flags = storedMetaData + .foldLeft[Flags](new Flags())((flags: Flags, m: ComposedMessageIdWithMetaData) => { + flags.add(m.getFlags) + flags + }) + val newFlags = update.keywordsTransformation + .apply(LENIENT_KEYWORDS_FACTORY.fromFlags(originalFlags).get) + .asFlagsWithRecentAndDeletedFrom(originalFlags) + SMono(messageIdManager.updateEmail(messageId, targetIds.value.asJava, newFlags, FlagsUpdateMode.REPLACE, session)) + .`then`(SMono.just[EmailUpdateResult](EmailUpdateSuccess(messageId))) + .onErrorResume(e => SMono.just[EmailUpdateResult](EmailUpdateFailure(EmailSet.asUnparsed(messageId), e))) + .switchIfEmpty(SMono.just[EmailUpdateResult](EmailUpdateSuccess(messageId))) + } else { + updateFlags(messageId, update, mailboxIds, storedMetaData, session) + .flatMap { + case failure: EmailUpdateFailure => SMono.just[EmailUpdateResult](failure) + case _: EmailUpdateSuccess => updateMailboxIds(messageId, update, mailboxIds, session) + } + .onErrorResume(e => SMono.just[EmailUpdateResult](EmailUpdateFailure(EmailSet.asUnparsed(messageId), e))) + .switchIfEmpty(SMono.just[EmailUpdateResult](EmailUpdateSuccess(messageId))) + } } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
