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
commit 1469c4a41cd7f083317d6d0efe44d6a278057f04 Author: Benoit Tellier <[email protected]> AuthorDate: Mon Apr 6 19:41:25 2020 +0700 JAMES-2997 Drop Cassandra schema version prior version 5 --- .../versions/CassandraSchemaVersionManager.java | 2 +- .../CassandraMailboxSessionMapperFactory.java | 7 +- .../cassandra/mail/CassandraAttachmentMapper.java | 11 +- .../migration/AttachmentMessageIdCreation.java | 62 ------ .../mail/migration/AttachmentV2Migration.java | 65 ------ .../CassandraSubscriptionManagerTest.java | 4 - .../cassandra/mail/CassandraAttachmentDAOTest.java | 118 ----------- .../mail/CassandraAttachmentFallbackTest.java | 180 ----------------- .../migration/AttachmentMessageIdCreationTest.java | 198 ------------------ .../mail/migration/AttachmentV2MigrationTest.java | 221 --------------------- .../SolveMailboxInconsistenciesServiceTest.java | 2 +- .../modules/mailbox/CassandraMailboxModule.java | 2 - .../modules/webadmin/CassandraRoutesModule.java | 8 - upgrade-instructions.md | 12 ++ 14 files changed, 18 insertions(+), 874 deletions(-) diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManager.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManager.java index ef56bdb..9b47f39 100644 --- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManager.java +++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/versions/CassandraSchemaVersionManager.java @@ -33,7 +33,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; public class CassandraSchemaVersionManager { - public static final SchemaVersion MIN_VERSION = new SchemaVersion(2); + public static final SchemaVersion MIN_VERSION = new SchemaVersion(5); public static final SchemaVersion MAX_VERSION = new SchemaVersion(7); public static final SchemaVersion DEFAULT_VERSION = MIN_VERSION; diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java index 301e28a..d6f506e 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java @@ -29,7 +29,6 @@ import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper; import org.apache.james.mailbox.cassandra.mail.CassandraAnnotationMapper; import org.apache.james.mailbox.cassandra.mail.CassandraApplicableFlagDAO; -import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMapper; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO; @@ -85,7 +84,6 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa private final CassandraMailboxPathV2DAO mailboxPathV2DAO; private final CassandraFirstUnseenDAO firstUnseenDAO; private final CassandraApplicableFlagDAO applicableFlagDAO; - private final CassandraAttachmentDAO attachmentDAO; private final CassandraAttachmentDAOV2 attachmentDAOV2; private final CassandraDeletedMessageDAO deletedMessageDAO; private final BlobStore blobStore; @@ -103,7 +101,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa CassandraMessageIdDAO messageIdDAO, CassandraMessageIdToImapUidDAO imapUidDAO, CassandraMailboxCounterDAO mailboxCounterDAO, CassandraMailboxRecentsDAO mailboxRecentsDAO, CassandraMailboxDAO mailboxDAO, CassandraMailboxPathDAOImpl mailboxPathDAO, CassandraMailboxPathV2DAO mailboxPathV2DAO, CassandraFirstUnseenDAO firstUnseenDAO, CassandraApplicableFlagDAO applicableFlagDAO, - CassandraAttachmentDAO attachmentDAO, CassandraAttachmentDAOV2 attachmentDAOV2, CassandraDeletedMessageDAO deletedMessageDAO, + CassandraAttachmentDAOV2 attachmentDAOV2, CassandraDeletedMessageDAO deletedMessageDAO, BlobStore blobStore, CassandraAttachmentMessageIdDAO attachmentMessageIdDAO, CassandraAttachmentOwnerDAO ownerDAO, CassandraACLMapper aclMapper, CassandraUserMailboxRightsDAO userMailboxRightsDAO, @@ -121,7 +119,6 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa this.mailboxPathDAO = mailboxPathDAO; this.mailboxPathV2DAO = mailboxPathV2DAO; this.firstUnseenDAO = firstUnseenDAO; - this.attachmentDAO = attachmentDAO; this.attachmentDAOV2 = attachmentDAOV2; this.deletedMessageDAO = deletedMessageDAO; this.applicableFlagDAO = applicableFlagDAO; @@ -174,7 +171,7 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa @Override public CassandraAttachmentMapper createAttachmentMapper(MailboxSession mailboxSession) { - return new CassandraAttachmentMapper(attachmentDAO, attachmentDAOV2, blobStore, attachmentMessageIdDAO, ownerDAO); + return new CassandraAttachmentMapper(attachmentDAOV2, blobStore, attachmentMessageIdDAO, ownerDAO); } @Override diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java index a2c4bad..9c7f0b2 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentMapper.java @@ -48,15 +48,13 @@ import reactor.core.publisher.Mono; public class CassandraAttachmentMapper implements AttachmentMapper { private static final Logger LOGGER = LoggerFactory.getLogger(CassandraAttachmentMapper.class); - private final CassandraAttachmentDAO attachmentDAO; private final CassandraAttachmentDAOV2 attachmentDAOV2; private final BlobStore blobStore; private final CassandraAttachmentMessageIdDAO attachmentMessageIdDAO; private final CassandraAttachmentOwnerDAO ownerDAO; @Inject - public CassandraAttachmentMapper(CassandraAttachmentDAO attachmentDAO, CassandraAttachmentDAOV2 attachmentDAOV2, BlobStore blobStore, CassandraAttachmentMessageIdDAO attachmentMessageIdDAO, CassandraAttachmentOwnerDAO ownerDAO) { - this.attachmentDAO = attachmentDAO; + public CassandraAttachmentMapper(CassandraAttachmentDAOV2 attachmentDAOV2, BlobStore blobStore, CassandraAttachmentMessageIdDAO attachmentMessageIdDAO, CassandraAttachmentOwnerDAO ownerDAO) { this.attachmentDAOV2 = attachmentDAOV2; this.blobStore = blobStore; this.attachmentMessageIdDAO = attachmentMessageIdDAO; @@ -101,12 +99,7 @@ public class CassandraAttachmentMapper implements AttachmentMapper { private Mono<Attachment> getAttachmentInternal(AttachmentId id) { return attachmentDAOV2.getAttachment(id) - .flatMap(this::retrievePayload) - .switchIfEmpty(fallbackToV1(id)); - } - - private Mono<Attachment> fallbackToV1(AttachmentId attachmentId) { - return attachmentDAO.getAttachment(attachmentId); + .flatMap(this::retrievePayload); } @Override diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreation.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreation.java deleted file mode 100644 index b70b8db..0000000 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreation.java +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************** - * 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.cassandra.mail.migration; - -import javax.inject.Inject; - -import org.apache.james.backends.cassandra.migration.Migration; -import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO; -import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; -import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO.MessageIdAttachmentIds; -import org.apache.james.mailbox.model.MessageId; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -public class AttachmentMessageIdCreation implements Migration { - private static final Logger LOGGER = LoggerFactory.getLogger(AttachmentMessageIdCreation.class); - private final CassandraMessageDAO cassandraMessageDAO; - private final CassandraAttachmentMessageIdDAO attachmentMessageIdDAO; - - @Inject - public AttachmentMessageIdCreation(CassandraMessageDAO cassandraMessageDAO, - CassandraAttachmentMessageIdDAO attachmentMessageIdDAO) { - this.cassandraMessageDAO = cassandraMessageDAO; - this.attachmentMessageIdDAO = attachmentMessageIdDAO; - } - - @Override - public void apply() { - cassandraMessageDAO.retrieveAllMessageIdAttachmentIds() - .flatMap(this::createIndex) - .doOnError(e -> LOGGER.error("Error while creation attachmentId -> messageIds index", e)) - .blockLast(); - } - - private Mono<Void> createIndex(MessageIdAttachmentIds message) { - MessageId messageId = message.getMessageId(); - return Flux.fromIterable(message.getAttachmentId()) - .flatMap(attachmentId -> attachmentMessageIdDAO.storeAttachmentForMessageId(attachmentId, messageId)) - .then(); - } - -} diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java deleted file mode 100644 index 020a8d5..0000000 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2Migration.java +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************** - * 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.cassandra.mail.migration; - -import static org.apache.james.blob.api.BlobStore.StoragePolicy.LOW_COST; - -import javax.inject.Inject; - -import org.apache.james.backends.cassandra.migration.Migration; -import org.apache.james.blob.api.BlobStore; -import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO; -import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2; -import org.apache.james.mailbox.model.Attachment; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import reactor.core.publisher.Mono; - -public class AttachmentV2Migration implements Migration { - private static final Logger LOGGER = LoggerFactory.getLogger(AttachmentV2Migration.class); - private final CassandraAttachmentDAO attachmentDAOV1; - private final CassandraAttachmentDAOV2 attachmentDAOV2; - private final BlobStore blobStore; - - @Inject - public AttachmentV2Migration(CassandraAttachmentDAO attachmentDAOV1, - CassandraAttachmentDAOV2 attachmentDAOV2, - BlobStore blobStore) { - this.attachmentDAOV1 = attachmentDAOV1; - this.attachmentDAOV2 = attachmentDAOV2; - this.blobStore = blobStore; - } - - @Override - public void apply() { - attachmentDAOV1.retrieveAll() - .flatMap(this::migrateAttachment) - .doOnError(t -> LOGGER.error("Error while performing attachmentDAO V2 migration", t)) - .blockLast(); - } - - private Mono<Void> migrateAttachment(Attachment attachment) { - return Mono.from(blobStore.save(blobStore.getDefaultBucketName(), attachment.getBytes(), LOW_COST)) - .map(blobId -> CassandraAttachmentDAOV2.from(attachment, blobId)) - .flatMap(attachmentDAOV2::storeAttachment) - .then(attachmentDAOV1.deleteAttachment(attachment.getAttachmentId())); - } -} diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java index a230e11..f555a7f 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraSubscriptionManagerTest.java @@ -22,14 +22,12 @@ package org.apache.james.mailbox.cassandra; import org.apache.james.backends.cassandra.CassandraClusterExtension; import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration; import org.apache.james.backends.cassandra.utils.CassandraUtils; -import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO; import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager; import org.apache.james.blob.api.BlobStore; import org.apache.james.mailbox.SubscriptionManager; import org.apache.james.mailbox.SubscriptionManagerContract; import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper; import org.apache.james.mailbox.cassandra.mail.CassandraApplicableFlagDAO; -import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO; @@ -78,7 +76,6 @@ class CassandraSubscriptionManagerTest implements SubscriptionManagerContract { CassandraMailboxPathV2DAO mailboxPathV2DAO = null; CassandraFirstUnseenDAO firstUnseenDAO = null; CassandraApplicableFlagDAO applicableFlagDAO = null; - CassandraAttachmentDAO attachmentDAO = null; CassandraDeletedMessageDAO deletedMessageDAO = null; CassandraAttachmentDAOV2 attachmentDAOV2 = null; CassandraAttachmentMessageIdDAO attachmentMessageIdDAO = null; @@ -105,7 +102,6 @@ class CassandraSubscriptionManagerTest implements SubscriptionManagerContract { mailboxPathV2DAO, firstUnseenDAO, applicableFlagDAO, - attachmentDAO, attachmentDAOV2, deletedMessageDAO, blobStore, diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOTest.java deleted file mode 100644 index ec41c87..0000000 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentDAOTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************** - * 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.cassandra.mail; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.nio.charset.StandardCharsets; -import java.util.Optional; - -import org.apache.james.backends.cassandra.CassandraCluster; -import org.apache.james.backends.cassandra.CassandraClusterExtension; -import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration; -import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; -import org.apache.james.mailbox.model.Attachment; -import org.apache.james.mailbox.model.AttachmentId; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -class CassandraAttachmentDAOTest { - private static final AttachmentId ATTACHMENT_ID = AttachmentId.from("id1"); - private static final AttachmentId ATTACHMENT_ID_2 = AttachmentId.from("id2"); - - @RegisterExtension - static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(CassandraAttachmentModule.MODULE); - - private CassandraAttachmentDAO testee; - - @BeforeEach - void setUp(CassandraCluster cassandra) { - testee = new CassandraAttachmentDAO(cassandra.getConf(), - CassandraConfiguration.DEFAULT_CONFIGURATION); - } - - @Test - void getAttachmentShouldReturnEmptyWhenAbsent() { - Optional<Attachment> attachment = testee.getAttachment(ATTACHMENT_ID).blockOptional(); - - assertThat(attachment).isEmpty(); - } - - @Test - void retrieveAllShouldReturnEmptyByDefault() { - assertThat( - testee.retrieveAll() - .collectList() - .block()) - .isEmpty(); - } - - @Test - void retrieveAllShouldReturnStoredAttachments() throws Exception { - Attachment attachment1 = Attachment.builder() - .attachmentId(ATTACHMENT_ID) - .type("application/json") - .bytes("{\"property\":`\"value1\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - Attachment attachment2 = Attachment.builder() - .attachmentId(ATTACHMENT_ID_2) - .type("application/json") - .bytes("{\"property\":`\"value2\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - testee.storeAttachment(attachment1).block(); - testee.storeAttachment(attachment2).block(); - - assertThat( - testee.retrieveAll() - .collectList() - .block()) - .containsOnly(attachment1, attachment2); - } - - @Test - void getAttachmentShouldReturnAttachmentWhenStored() throws Exception { - Attachment attachment = Attachment.builder() - .attachmentId(ATTACHMENT_ID) - .type("application/json") - .bytes("{\"property\":`\"value\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - testee.storeAttachment(attachment).block(); - - Optional<Attachment> actual = testee.getAttachment(ATTACHMENT_ID).blockOptional(); - - assertThat(actual).contains(attachment); - } - - @Test - void deleteAttachmentShouldRemoveAttachment() throws Exception { - Attachment attachment = Attachment.builder() - .attachmentId(ATTACHMENT_ID) - .type("application/json") - .bytes("{\"property\":`\"value\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - testee.storeAttachment(attachment).block(); - - testee.deleteAttachment(attachment.getAttachmentId()).block(); - - assertThat(testee.getAttachment(attachment.getAttachmentId()).blockOptional()) - .isEmpty(); - } -} diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java deleted file mode 100644 index 98aacf0..0000000 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraAttachmentFallbackTest.java +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************** - * 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.cassandra.mail; - -import static org.apache.james.blob.api.BlobStore.StoragePolicy.LOW_COST; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import org.apache.james.backends.cassandra.CassandraCluster; -import org.apache.james.backends.cassandra.CassandraClusterExtension; -import org.apache.james.backends.cassandra.components.CassandraModule; -import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration; -import org.apache.james.blob.api.BlobId; -import org.apache.james.blob.api.HashBlobId; -import org.apache.james.blob.cassandra.CassandraBlobModule; -import org.apache.james.blob.cassandra.CassandraBlobStore; -import org.apache.james.mailbox.cassandra.ids.CassandraMessageId; -import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; -import org.apache.james.mailbox.exception.AttachmentNotFoundException; -import org.apache.james.mailbox.model.Attachment; -import org.apache.james.mailbox.model.AttachmentId; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import com.google.common.collect.ImmutableList; - -class CassandraAttachmentFallbackTest { - private static final AttachmentId ATTACHMENT_ID_1 = AttachmentId.from("id1"); - private static final AttachmentId ATTACHMENT_ID_2 = AttachmentId.from("id2"); - private static final HashBlobId.Factory BLOB_ID_FACTORY = new HashBlobId.Factory(); - - @RegisterExtension - static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension( - CassandraModule.aggregateModules( - CassandraAttachmentModule.MODULE, - CassandraBlobModule.MODULE)); - - private CassandraAttachmentDAOV2 attachmentDAOV2; - private CassandraAttachmentDAO attachmentDAO; - private CassandraAttachmentMapper attachmentMapper; - private CassandraBlobStore blobStore; - private CassandraAttachmentMessageIdDAO attachmentMessageIdDAO; - - - @BeforeEach - void setUp(CassandraCluster cassandra) { - attachmentDAOV2 = new CassandraAttachmentDAOV2(BLOB_ID_FACTORY, cassandra.getConf()); - attachmentDAO = new CassandraAttachmentDAO(cassandra.getConf(), - CassandraConfiguration.DEFAULT_CONFIGURATION); - blobStore = CassandraBlobStore.forTesting(cassandra.getConf()); - attachmentMessageIdDAO = new CassandraAttachmentMessageIdDAO(cassandra.getConf(), new CassandraMessageId.Factory()); - CassandraAttachmentOwnerDAO ownerDAO = new CassandraAttachmentOwnerDAO(cassandra.getConf()); - attachmentMapper = new CassandraAttachmentMapper(attachmentDAO, attachmentDAOV2, blobStore, attachmentMessageIdDAO, ownerDAO); - } - - @Test - void getAttachmentShouldThrowWhenAbsentFromV1AndV2() { - assertThatThrownBy(() -> attachmentMapper.getAttachment(ATTACHMENT_ID_1)) - .isInstanceOf(AttachmentNotFoundException.class); - } - - @Test - void getAttachmentsShouldReturnEmptyWhenAbsentFromV1AndV2() { - assertThat(attachmentMapper.getAttachments(ImmutableList.of(ATTACHMENT_ID_1))) - .isEmpty(); - } - - @Test - void getAttachmentShouldReturnV2WhenPresentInV1AndV2() throws Exception { - Attachment attachment = Attachment.builder() - .attachmentId(ATTACHMENT_ID_1) - .type("application/json") - .bytes("{\"property\":`\"value\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - Attachment otherAttachment = Attachment.builder() - .attachmentId(ATTACHMENT_ID_1) - .type("application/json") - .bytes("{\"property\":`\"different\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - - BlobId blobId = blobStore.save(blobStore.getDefaultBucketName(), attachment.getBytes(), LOW_COST).block(); - attachmentDAOV2.storeAttachment(CassandraAttachmentDAOV2.from(attachment, blobId)).block(); - attachmentDAO.storeAttachment(otherAttachment).block(); - - assertThat(attachmentMapper.getAttachment(ATTACHMENT_ID_1)) - .isEqualTo(attachment); - } - - @Test - void getAttachmentShouldReturnV1WhenV2Absent() throws Exception { - Attachment attachment = Attachment.builder() - .attachmentId(ATTACHMENT_ID_1) - .type("application/json") - .bytes("{\"property\":`\"value\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - - attachmentDAO.storeAttachment(attachment).block(); - - assertThat(attachmentMapper.getAttachment(ATTACHMENT_ID_1)) - .isEqualTo(attachment); - } - - @Test - void getAttachmentsShouldReturnV2WhenV2AndV1() throws Exception { - Attachment attachment = Attachment.builder() - .attachmentId(ATTACHMENT_ID_1) - .type("application/json") - .bytes("{\"property\":`\"value\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - Attachment otherAttachment = Attachment.builder() - .attachmentId(ATTACHMENT_ID_1) - .type("application/json") - .bytes("{\"property\":`\"different\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - - BlobId blobId = blobStore.save(blobStore.getDefaultBucketName(), attachment.getBytes(), LOW_COST).block(); - attachmentDAOV2.storeAttachment(CassandraAttachmentDAOV2.from(attachment, blobId)).block(); - attachmentDAO.storeAttachment(otherAttachment).block(); - - assertThat(attachmentMapper.getAttachments(ImmutableList.of(ATTACHMENT_ID_1))) - .containsExactly(attachment); - } - - @Test - void getAttachmentsShouldReturnV1WhenV2Absent() throws Exception { - Attachment attachment = Attachment.builder() - .attachmentId(ATTACHMENT_ID_1) - .type("application/json") - .bytes("{\"property\":`\"value\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - - attachmentDAO.storeAttachment(attachment).block(); - - assertThat(attachmentMapper.getAttachments(ImmutableList.of(ATTACHMENT_ID_1))) - .containsExactly(attachment); - } - - @Test - void getAttachmentsShouldCombineElementsFromV1AndV2() throws Exception { - Attachment attachment = Attachment.builder() - .attachmentId(ATTACHMENT_ID_1) - .type("application/json") - .bytes("{\"property\":`\"value\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - Attachment otherAttachment = Attachment.builder() - .attachmentId(ATTACHMENT_ID_2) - .type("application/json") - .bytes("{\"property\":`\"different\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - - BlobId blobId = blobStore.save(blobStore.getDefaultBucketName(), attachment.getBytes(), LOW_COST).block(); - attachmentDAOV2.storeAttachment(CassandraAttachmentDAOV2.from(attachment, blobId)).block(); - attachmentDAO.storeAttachment(otherAttachment).block(); - - List<Attachment> attachments = attachmentMapper.getAttachments(ImmutableList.of(ATTACHMENT_ID_1, ATTACHMENT_ID_2)); - assertThat(attachments) - .containsExactlyInAnyOrder(attachment, otherAttachment); - } -} diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java deleted file mode 100644 index 531c719..0000000 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentMessageIdCreationTest.java +++ /dev/null @@ -1,198 +0,0 @@ -/**************************************************************** - * 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.cassandra.mail.migration; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.Date; -import java.util.List; - -import javax.mail.Flags; -import javax.mail.util.SharedByteArrayInputStream; - -import org.apache.james.backends.cassandra.CassandraCluster; -import org.apache.james.backends.cassandra.CassandraClusterExtension; -import org.apache.james.backends.cassandra.components.CassandraModule; -import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule; -import org.apache.james.blob.api.HashBlobId; -import org.apache.james.blob.cassandra.CassandraBlobModule; -import org.apache.james.blob.cassandra.CassandraBlobStore; -import org.apache.james.mailbox.MessageUid; -import org.apache.james.mailbox.cassandra.ids.CassandraId; -import org.apache.james.mailbox.cassandra.ids.CassandraMessageId; -import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO; -import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO; -import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; -import org.apache.james.mailbox.cassandra.modules.CassandraMessageModule; -import org.apache.james.mailbox.model.Attachment; -import org.apache.james.mailbox.model.AttachmentId; -import org.apache.james.mailbox.model.MessageAttachment; -import org.apache.james.mailbox.model.MessageId; -import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder; -import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage; -import org.apache.james.task.Task; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -import reactor.core.publisher.Flux; - -class AttachmentMessageIdCreationTest { - public static final CassandraModule MODULES = CassandraModule.aggregateModules( - CassandraMessageModule.MODULE, - CassandraAttachmentModule.MODULE, - CassandraBlobModule.MODULE, - CassandraSchemaVersionModule.MODULE); - - @RegisterExtension - static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension( - MODULES); - - private CassandraBlobStore blobStore; - private CassandraMessageDAO cassandraMessageDAO; - private CassandraAttachmentMessageIdDAO attachmentMessageIdDAO; - - private AttachmentMessageIdCreation migration; - - private SimpleMailboxMessage message; - private CassandraMessageId messageId; - - @BeforeEach - void setUp(CassandraCluster cassandra) { - CassandraMessageId.Factory messageIdFactory = new CassandraMessageId.Factory(); - - blobStore = CassandraBlobStore.forTesting(cassandra.getConf()); - cassandraMessageDAO = new CassandraMessageDAO(cassandra.getConf(), cassandra.getTypesProvider(), - blobStore, new HashBlobId.Factory(), messageIdFactory); - - attachmentMessageIdDAO = new CassandraAttachmentMessageIdDAO(cassandra.getConf(), - new CassandraMessageId.Factory()); - - migration = new AttachmentMessageIdCreation(cassandraMessageDAO, attachmentMessageIdDAO); - - messageId = messageIdFactory.generate(); - } - - @Test - void emptyMigrationShouldSucceed() throws InterruptedException { - assertThat(migration.asTask().run()) - .isEqualTo(Task.Result.COMPLETED); - } - - @Test - void migrationShouldSucceedWhenNoAttachment() throws Exception { - List<MessageAttachment> noAttachment = ImmutableList.of(); - message = createMessage(messageId, noAttachment); - - cassandraMessageDAO.save(message).block(); - - assertThat(migration.asTask().run()) - .isEqualTo(Task.Result.COMPLETED); - } - - @Test - void migrationShouldSucceedWhenAttachment() throws Exception { - MessageAttachment attachment = createAttachment(); - message = createMessage(messageId, ImmutableList.of(attachment)); - - cassandraMessageDAO.save(message).block(); - - assertThat(migration.asTask().run()) - .isEqualTo(Task.Result.COMPLETED); - } - - @Test - void migrationShouldCreateAttachmentIdOnAttachmentMessageIdTableFromMessage() throws Exception { - MessageAttachment attachment = createAttachment(); - message = createMessage(messageId, ImmutableList.of(attachment)); - - cassandraMessageDAO.save(message).block(); - - migration.apply(); - - assertThat(attachmentMessageIdDAO.getOwnerMessageIds(attachment.getAttachmentId()).toIterable()) - .containsExactly(messageId); - } - - @Test - void migrationShouldReturnPartialWhenRetrieveAllAttachmentIdFromMessageFail() throws Exception { - CassandraMessageDAO cassandraMessageDAO = mock(CassandraMessageDAO.class); - CassandraAttachmentMessageIdDAO attachmentMessageIdDAO = mock(CassandraAttachmentMessageIdDAO.class); - migration = new AttachmentMessageIdCreation(cassandraMessageDAO, attachmentMessageIdDAO); - - when(cassandraMessageDAO.retrieveAllMessageIdAttachmentIds()).thenReturn(Flux.error(new RuntimeException("Mocked exception"))); - - assertThat(migration.asTask().run()).isEqualTo(Task.Result.PARTIAL); - } - - @Test - void migrationShouldReturnPartialWhenSavingAttachmentIdForMessageIdFail() throws Exception { - CassandraMessageDAO cassandraMessageDAO = mock(CassandraMessageDAO.class); - CassandraAttachmentMessageIdDAO attachmentMessageIdDAO = mock(CassandraAttachmentMessageIdDAO.class); - CassandraMessageDAO.MessageIdAttachmentIds messageIdAttachmentIds = mock(CassandraMessageDAO.MessageIdAttachmentIds.class); - - migration = new AttachmentMessageIdCreation(cassandraMessageDAO, attachmentMessageIdDAO); - - when(messageIdAttachmentIds.getAttachmentId()).thenReturn(ImmutableSet.of(AttachmentId.from("any"))); - when(cassandraMessageDAO.retrieveAllMessageIdAttachmentIds()) - .thenReturn(Flux.just(messageIdAttachmentIds)); - when(attachmentMessageIdDAO.storeAttachmentForMessageId(any(AttachmentId.class), any(MessageId.class))) - .thenThrow(new RuntimeException()); - - assertThat(migration.asTask().run()).isEqualTo(Task.Result.PARTIAL); - } - - private SimpleMailboxMessage createMessage(MessageId messageId, Collection<MessageAttachment> attachments) { - MessageUid messageUid = MessageUid.of(1); - CassandraId mailboxId = CassandraId.timeBased(); - String content = "Subject: Any subject \n\nThis is the body\n.\n"; - int bodyStart = 22; - - return SimpleMailboxMessage.builder() - .messageId(messageId) - .mailboxId(mailboxId) - .uid(messageUid) - .internalDate(new Date()) - .bodyStartOctet(bodyStart) - .size(content.length()) - .content(new SharedByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8))) - .flags(new Flags()) - .propertyBuilder(new PropertyBuilder()) - .addAttachments(attachments) - .build(); - } - - private MessageAttachment createAttachment() { - return MessageAttachment.builder() - .attachment(Attachment.builder() - .bytes("content".getBytes(StandardCharsets.UTF_8)) - .type("type") - .build()) - .build(); - } -} \ No newline at end of file diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java deleted file mode 100644 index 4e40a47..0000000 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AttachmentV2MigrationTest.java +++ /dev/null @@ -1,221 +0,0 @@ -/**************************************************************** - * 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.cassandra.mail.migration; - -import static org.apache.james.blob.api.BlobStore.StoragePolicy.LOW_COST; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.nio.charset.StandardCharsets; - -import org.apache.james.backends.cassandra.CassandraCluster; -import org.apache.james.backends.cassandra.CassandraClusterExtension; -import org.apache.james.backends.cassandra.components.CassandraModule; -import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration; -import org.apache.james.blob.api.BucketName; -import org.apache.james.blob.api.HashBlobId; -import org.apache.james.blob.cassandra.CassandraBlobModule; -import org.apache.james.blob.cassandra.CassandraBlobStore; -import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO; -import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2; -import org.apache.james.mailbox.cassandra.modules.CassandraAttachmentModule; -import org.apache.james.mailbox.model.Attachment; -import org.apache.james.mailbox.model.AttachmentId; -import org.apache.james.task.Task; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -class AttachmentV2MigrationTest { - private static final AttachmentId ATTACHMENT_ID = AttachmentId.from("id1"); - private static final AttachmentId ATTACHMENT_ID_2 = AttachmentId.from("id2"); - private static final HashBlobId.Factory BLOB_ID_FACTORY = new HashBlobId.Factory(); - - @RegisterExtension - static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension( - CassandraModule.aggregateModules( - CassandraAttachmentModule.MODULE, - CassandraBlobModule.MODULE)); - - private CassandraAttachmentDAO attachmentDAO; - private CassandraAttachmentDAOV2 attachmentDAOV2; - private CassandraBlobStore blobsStore; - private AttachmentV2Migration migration; - private Attachment attachment1; - private Attachment attachment2; - - @BeforeEach - void setUp(CassandraCluster cassandra) { - attachmentDAO = new CassandraAttachmentDAO(cassandra.getConf(), - CassandraConfiguration.DEFAULT_CONFIGURATION); - attachmentDAOV2 = new CassandraAttachmentDAOV2(BLOB_ID_FACTORY, cassandra.getConf()); - blobsStore = CassandraBlobStore.forTesting(cassandra.getConf()); - migration = new AttachmentV2Migration(attachmentDAO, attachmentDAOV2, blobsStore); - - attachment1 = Attachment.builder() - .attachmentId(ATTACHMENT_ID) - .type("application/json") - .bytes("{\"property\":`\"value1\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - attachment2 = Attachment.builder() - .attachmentId(ATTACHMENT_ID_2) - .type("application/json") - .bytes("{\"property\":`\"value2\"}".getBytes(StandardCharsets.UTF_8)) - .build(); - } - - @Test - void emptyMigrationShouldSucceed() throws InterruptedException { - assertThat(migration.asTask().run()) - .isEqualTo(Task.Result.COMPLETED); - } - - @Test - void migrationShouldSucceed() throws Exception { - attachmentDAO.storeAttachment(attachment1).block(); - attachmentDAO.storeAttachment(attachment2).block(); - - assertThat(migration.asTask().run()) - .isEqualTo(Task.Result.COMPLETED); - } - - @Test - void migrationShouldMoveAttachmentsToV2() throws Exception { - attachmentDAO.storeAttachment(attachment1).block(); - attachmentDAO.storeAttachment(attachment2).block(); - - migration.apply(); - - assertThat(attachmentDAOV2.getAttachment(ATTACHMENT_ID).blockOptional()) - .contains(CassandraAttachmentDAOV2.from(attachment1, BLOB_ID_FACTORY.forPayload(attachment1.getBytes()))); - assertThat(attachmentDAOV2.getAttachment(ATTACHMENT_ID_2).blockOptional()) - .contains(CassandraAttachmentDAOV2.from(attachment2, BLOB_ID_FACTORY.forPayload(attachment2.getBytes()))); - assertThat(blobsStore.readBytes(blobsStore.getDefaultBucketName(), BLOB_ID_FACTORY.forPayload(attachment1.getBytes())).block()) - .isEqualTo(attachment1.getBytes()); - assertThat(blobsStore.readBytes(blobsStore.getDefaultBucketName(), BLOB_ID_FACTORY.forPayload(attachment2.getBytes())).block()) - .isEqualTo(attachment2.getBytes()); - } - - @Test - void migrationShouldRemoveAttachmentsFromV1() throws Exception { - attachmentDAO.storeAttachment(attachment1).block(); - attachmentDAO.storeAttachment(attachment2).block(); - - migration.apply(); - - assertThat(attachmentDAO.getAttachment(ATTACHMENT_ID).blockOptional()) - .isEmpty(); - assertThat(attachmentDAO.getAttachment(ATTACHMENT_ID_2).blockOptional()) - .isEmpty(); - } - - @Test - void runShouldReturnPartialWhenInitialReadFail() throws InterruptedException { - CassandraAttachmentDAO attachmentDAO = mock(CassandraAttachmentDAO.class); - CassandraAttachmentDAOV2 attachmentDAOV2 = mock(CassandraAttachmentDAOV2.class); - CassandraBlobStore blobsStore = mock(CassandraBlobStore.class); - migration = new AttachmentV2Migration(attachmentDAO, attachmentDAOV2, blobsStore); - - when(attachmentDAO.retrieveAll()).thenReturn(Flux.error(new RuntimeException())); - - assertThat(migration.asTask().run()).isEqualTo(Task.Result.PARTIAL); - } - - @Test - void runShouldReturnPartialWhenSavingBlobsFails() throws InterruptedException { - CassandraAttachmentDAO attachmentDAO = mock(CassandraAttachmentDAO.class); - CassandraAttachmentDAOV2 attachmentDAOV2 = mock(CassandraAttachmentDAOV2.class); - CassandraBlobStore blobsStore = mock(CassandraBlobStore.class); - migration = new AttachmentV2Migration(attachmentDAO, attachmentDAOV2, blobsStore); - - when(attachmentDAO.retrieveAll()).thenReturn(Flux.just( - attachment1, - attachment2)); - when(blobsStore.save(any(BucketName.class), any(byte[].class), eq(LOW_COST))).thenThrow(new RuntimeException()); - - assertThat(migration.asTask().run()).isEqualTo(Task.Result.PARTIAL); - } - - @Test - void runShouldReturnPartialWhenSavingAttachmentV2Fail() throws InterruptedException { - CassandraAttachmentDAO attachmentDAO = mock(CassandraAttachmentDAO.class); - CassandraAttachmentDAOV2 attachmentDAOV2 = mock(CassandraAttachmentDAOV2.class); - CassandraBlobStore blobsStore = mock(CassandraBlobStore.class); - migration = new AttachmentV2Migration(attachmentDAO, attachmentDAOV2, blobsStore); - - when(attachmentDAO.retrieveAll()).thenReturn(Flux.just( - attachment1, - attachment2)); - when(blobsStore.save(blobsStore.getDefaultBucketName(), attachment1.getBytes(), LOW_COST)) - .thenReturn(Mono.just(BLOB_ID_FACTORY.forPayload(attachment1.getBytes()))); - when(blobsStore.save(blobsStore.getDefaultBucketName(), attachment2.getBytes(), LOW_COST)) - .thenReturn(Mono.just(BLOB_ID_FACTORY.forPayload(attachment2.getBytes()))); - when(attachmentDAOV2.storeAttachment(any())).thenThrow(new RuntimeException()); - - assertThat(migration.asTask().run()).isEqualTo(Task.Result.PARTIAL); - } - - @Test - void runShouldReturnPartialWhenDeleteV1AttachmentFail() throws InterruptedException { - CassandraAttachmentDAO attachmentDAO = mock(CassandraAttachmentDAO.class); - CassandraAttachmentDAOV2 attachmentDAOV2 = mock(CassandraAttachmentDAOV2.class); - CassandraBlobStore blobsStore = mock(CassandraBlobStore.class); - migration = new AttachmentV2Migration(attachmentDAO, attachmentDAOV2, blobsStore); - - when(attachmentDAO.retrieveAll()).thenReturn(Flux.just( - attachment1, - attachment2)); - when(blobsStore.save(blobsStore.getDefaultBucketName(), attachment1.getBytes(), LOW_COST)) - .thenReturn(Mono.just(BLOB_ID_FACTORY.forPayload(attachment1.getBytes()))); - when(blobsStore.save(blobsStore.getDefaultBucketName(), attachment2.getBytes(), LOW_COST)) - .thenReturn(Mono.just(BLOB_ID_FACTORY.forPayload(attachment2.getBytes()))); - when(attachmentDAOV2.storeAttachment(any())).thenReturn(Mono.empty()); - when(attachmentDAO.deleteAttachment(any())).thenThrow(new RuntimeException()); - - assertThat(migration.asTask().run()).isEqualTo(Task.Result.PARTIAL); - } - - @Test - void runShouldReturnPartialWhenAtLeastOneAttachmentMigrationFails() throws InterruptedException { - CassandraAttachmentDAO attachmentDAO = mock(CassandraAttachmentDAO.class); - CassandraAttachmentDAOV2 attachmentDAOV2 = mock(CassandraAttachmentDAOV2.class); - CassandraBlobStore blobsStore = mock(CassandraBlobStore.class); - migration = new AttachmentV2Migration(attachmentDAO, attachmentDAOV2, blobsStore); - - when(attachmentDAO.retrieveAll()).thenReturn(Flux.just( - attachment1, - attachment2)); - when(blobsStore.save(blobsStore.getDefaultBucketName(), attachment1.getBytes(), LOW_COST)) - .thenReturn(Mono.just(BLOB_ID_FACTORY.forPayload(attachment1.getBytes()))); - when(blobsStore.save(blobsStore.getDefaultBucketName(), attachment2.getBytes(), LOW_COST)) - .thenThrow(new RuntimeException()); - when(attachmentDAOV2.storeAttachment(any())).thenReturn(Mono.empty()); - when(attachmentDAO.deleteAttachment(any())).thenReturn(Mono.empty()); - - assertThat(migration.asTask().run()).isEqualTo(Task.Result.PARTIAL); - } - -} diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMailboxInconsistenciesServiceTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMailboxInconsistenciesServiceTest.java index b99367a..5b9b1ec 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMailboxInconsistenciesServiceTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/task/SolveMailboxInconsistenciesServiceTest.java @@ -97,7 +97,7 @@ class SolveMailboxInconsistenciesServiceTest { assertThatThrownBy(() -> testee.fixMailboxInconsistencies(new Context()).block()) .isInstanceOf(IllegalStateException.class) - .hasMessage("Schema version 6 is required in order to ensure mailboxPathV2DAO to be correctly populated, got 2"); + .hasMessage("Schema version 6 is required in order to ensure mailboxPathV2DAO to be correctly populated, got 5"); } @Test diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java index 2733ac6..80d5579 100644 --- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java +++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java @@ -39,7 +39,6 @@ import org.apache.james.mailbox.cassandra.ids.CassandraId; import org.apache.james.mailbox.cassandra.ids.CassandraMessageId; import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper; import org.apache.james.mailbox.cassandra.mail.CassandraApplicableFlagDAO; -import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAO; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO; import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO; @@ -111,7 +110,6 @@ public class CassandraMailboxModule extends AbstractModule { install(new CassandraDeadLetterModule()); bind(CassandraApplicableFlagDAO.class).in(Scopes.SINGLETON); - bind(CassandraAttachmentDAO.class).in(Scopes.SINGLETON); bind(CassandraAttachmentDAOV2.class).in(Scopes.SINGLETON); bind(CassandraAttachmentMessageIdDAO.class).in(Scopes.SINGLETON); bind(CassandraAttachmentOwnerDAO.class).in(Scopes.SINGLETON); diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/webadmin/CassandraRoutesModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/webadmin/CassandraRoutesModule.java index 8812df0..23a4f0a 100644 --- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/webadmin/CassandraRoutesModule.java +++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/webadmin/CassandraRoutesModule.java @@ -25,8 +25,6 @@ import org.apache.james.backends.cassandra.migration.MigrationTask; import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager; import org.apache.james.backends.cassandra.versions.SchemaTransition; import org.apache.james.backends.cassandra.versions.SchemaVersion; -import org.apache.james.mailbox.cassandra.mail.migration.AttachmentMessageIdCreation; -import org.apache.james.mailbox.cassandra.mail.migration.AttachmentV2Migration; import org.apache.james.mailbox.cassandra.mail.migration.MailboxPathV2Migration; import org.apache.james.rrt.cassandra.migration.MappingsSourcesMigration; import org.apache.james.webadmin.Routes; @@ -40,9 +38,6 @@ import com.google.inject.multibindings.Multibinder; import com.google.inject.name.Names; public class CassandraRoutesModule extends AbstractModule { - private static final SchemaTransition FROM_V2_TO_V3 = SchemaTransition.to(new SchemaVersion(3)); - private static final SchemaTransition FROM_V3_TO_V4 = SchemaTransition.to(new SchemaVersion(4)); - private static final SchemaTransition FROM_V4_TO_V5 = SchemaTransition.to(new SchemaVersion(5)); private static final SchemaTransition FROM_V5_TO_V6 = SchemaTransition.to(new SchemaVersion(6)); private static final SchemaTransition FROM_V6_TO_V7 = SchemaTransition.to(new SchemaVersion(7)); @@ -60,9 +55,6 @@ public class CassandraRoutesModule extends AbstractModule { routesMultibinder.addBinding().to(CassandraMailboxMergingRoutes.class); MapBinder<SchemaTransition, Migration> allMigrationClazzBinder = MapBinder.newMapBinder(binder(), SchemaTransition.class, Migration.class); - allMigrationClazzBinder.addBinding(FROM_V2_TO_V3).toInstance(() -> { }); - allMigrationClazzBinder.addBinding(FROM_V3_TO_V4).to(AttachmentV2Migration.class); - allMigrationClazzBinder.addBinding(FROM_V4_TO_V5).to(AttachmentMessageIdCreation.class); allMigrationClazzBinder.addBinding(FROM_V5_TO_V6).to(MailboxPathV2Migration.class); allMigrationClazzBinder.addBinding(FROM_V6_TO_V7).to(MappingsSourcesMigration.class); diff --git a/upgrade-instructions.md b/upgrade-instructions.md index 399451a..4f7c11d 100644 --- a/upgrade-instructions.md +++ b/upgrade-instructions.md @@ -33,6 +33,18 @@ Change list: - [ProtocolSession storng typing](#protocolsession-storng-typing) - [Tune Cassandra time serie tables options](#tune-cassandra-time-serie-tables-options) - [Log4J2 Adoption](#log4j2-adoption) + - [Drop Cassandra schema version prior version 5](#drop-cassandra-schema-version-prior-version-5) + +### Drop Cassandra schema version prior version 5 + +Date 06/04/2020 + +JIRA: https://issues.apache.org/jira/browse/JAMES-2997 + +In an effort to simplify the code base, we dropped support for Cassandra schema version prior version 5. + +Installation running older schema version than version 5 needs to rely on release 3.5.0 to upgrade to schema version 7, +before upgrading to an eventual newer version. ### Log4J2 Adoption --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
