You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2026/06/18 05:53:11 UTC
(james-project) 06/12: [FIX] Cassandra folder rename: base decision on truth table
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
commit 986b76d02b70e986c0cbc27ed83ca9b603648192
Author: Benoit TELLIER <bt...@linagora.com>
AuthorDate: Tue Jun 16 17:36:28 2026 +0200
[FIX] Cassandra folder rename: base decision on truth table
Carry over truth table from MailboxManager
---
.../cassandra/mail/CassandraMailboxMapper.java | 28 +++++++++++-----------
.../james/mailbox/store/StoreMailboxManager.java | 4 ++--
.../james/mailbox/store/mail/MailboxMapper.java | 6 ++++-
.../java/org/apache/james/util/ReactorUtils.java | 11 +++++++++
4 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
index cb7e2b0eed..eceec29a4b 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapper.java
@@ -44,7 +44,7 @@ import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.model.UidValidity;
import org.apache.james.mailbox.model.search.MailboxQuery;
import org.apache.james.mailbox.store.mail.MailboxMapper;
-import org.apache.james.util.FunctionalUtils;
+import org.apache.james.util.ReactorUtils;
import com.google.common.base.Preconditions;
@@ -221,23 +221,23 @@ public class CassandraMailboxMapper implements MailboxMapper {
Preconditions.checkNotNull(mailbox.getMailboxId(), "A mailbox we want to rename should have a defined mailboxId");
CassandraId cassandraId = (CassandraId) mailbox.getMailboxId();
- return tryRename(mailbox, cassandraId)
- .filter(FunctionalUtils.identityPredicate())
- .switchIfEmpty(Mono.error(() -> new MailboxExistsException(mailbox.generateAssociatedPath().asString())))
- .thenReturn(cassandraId);
- }
-
- private Mono<Boolean> tryRename(Mailbox cassandraMailbox, CassandraId cassandraId) {
return mailboxDAO.retrieveMailbox(cassandraId)
- .flatMap(mailbox -> mailboxPathV3DAO.save(cassandraMailbox)
- .filter(isCreated -> isCreated)
- .flatMap(mailboxHasCreated -> deletePreviousMailboxPathReference(mailbox.generateAssociatedPath())
- .then(persistMailboxEntity(cassandraMailbox))
- .thenReturn(true))
- .defaultIfEmpty(false))
+ .flatMap(storedMailbox -> rename(mailbox, storedMailbox.generateAssociatedPath()))
.switchIfEmpty(Mono.error(() -> new MailboxNotFoundException(cassandraId)));
}
+ @Override
+ public Mono<MailboxId> rename(Mailbox cassandraMailbox, MailboxPath previousPath) {
+ Preconditions.checkNotNull(cassandraMailbox.getMailboxId(), "A mailbox we want to rename should have a defined mailboxId");
+ CassandraId cassandraId = (CassandraId) cassandraMailbox.getMailboxId();
+
+ return mailboxPathV3DAO.save(cassandraMailbox)
+ .handle(ReactorUtils.raiseErrorIfFalse(() -> new MailboxExistsException(cassandraMailbox.generateAssociatedPath().asString())))
+ .flatMap(applied -> deletePreviousMailboxPathReference(previousPath)
+ .then(persistMailboxEntity(cassandraMailbox)))
+ .thenReturn(cassandraId);
+ }
+
private Mono<Void> persistMailboxEntity(Mailbox cassandraMailbox) {
return mailboxDAO.save(cassandraMailbox)
.retryWhen(Retry.backoff(MAX_RETRY, MIN_RETRY_BACKOFF).maxBackoff(MAX_RETRY_BACKOFF));
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
index 475c1ba003..44ce721635 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
@@ -723,7 +723,7 @@ public class StoreMailboxManager implements MailboxManager {
.build()
.asUserBound();
- return mapper.rename(mailbox)
+ return mapper.rename(mailbox, from)
.map(mailboxId -> {
resultBuilder.add(new MailboxRenamedResult(mailboxId, from, newMailboxPath));
return mailboxId;
@@ -754,7 +754,7 @@ public class StoreMailboxManager implements MailboxManager {
MailboxPath fromPath = new MailboxPath(from, subOriginalName);
sub.setName(subNewName);
sub.setUser(newMailboxPath.getUser());
- return mapper.rename(sub)
+ return mapper.rename(sub, fromPath)
.map(mailboxId -> {
resultBuilder.add(new MailboxRenamedResult(sub.getMailboxId(), fromPath, sub.generateAssociatedPath()));
return mailboxId;
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
index a88d6a1012..3412efe295 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
@@ -50,8 +50,12 @@ public interface MailboxMapper extends Mapper {
/**
* Rename the given {@link Mailbox} to the underlying storage
*/
+ default Mono<MailboxId> rename(Mailbox mailbox, MailboxPath previousPath) {
+ return rename(mailbox);
+ }
+
Mono<MailboxId> rename(Mailbox mailbox);
-
+
/**
* Delete the given {@link Mailbox} from the underlying storage
*/
diff --git a/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java b/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java
index 0f69d237cf..4845ba437e 100644
--- a/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java
+++ b/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java
@@ -28,6 +28,7 @@ import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
+import java.util.function.Supplier;
import java.util.stream.Stream;
import org.reactivestreams.Publisher;
@@ -107,6 +108,16 @@ public class ReactorUtils {
return (element, sink) -> element.ifPresent(sink::next);
}
+ public static BiConsumer<Boolean, SynchronousSink<Boolean>> raiseErrorIfFalse(Supplier<Exception> exceptionSupplier) {
+ return (element, sink) -> {
+ if (!element) {
+ sink.error(exceptionSupplier.get());
+ } else {
+ sink.next(element);
+ }
+ };
+ }
+
public static InputStream toInputStream(Flux<ByteBuffer> byteArrays) {
return new StreamInputStream(byteArrays.toStream(DEFAULT_INPUT_STREAM_PREFETCH));
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org