From 164253ba3661afc26672c86d0b9991f8cf2b2d66 Mon Sep 17 00:00:00 2001 From: Oliver Santana Date: Mon, 2 Mar 2026 08:40:00 +0000 Subject: [PATCH 01/10] feat: added skipImport flag to MongockSupport annotation --- .../common/core/metadata/Constants.java | 1 + .../support/mongock/MongockImportChange.java | 20 +++++++++++++++++-- .../mongock/annotations/MongockSupport.java | 14 +++++++++++++ .../MongockAnnotationProcessorPlugin.java | 13 ++++++++++-- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/metadata/Constants.java b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/metadata/Constants.java index 07e327669..019acd5a9 100644 --- a/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/metadata/Constants.java +++ b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/metadata/Constants.java @@ -23,6 +23,7 @@ public final class Constants { public static final String DEFAULT_MONGOCK_ORIGIN = "mongockChangeLog"; + public static final String MONGOCK_IMPORT_SKIP_PROPERTY_KEY = "internal.mongock.import.skip"; public static final String MONGOCK_IMPORT_ORIGIN_PROPERTY_KEY = "internal.mongock.import.origin"; public static final String MONGOCK_IMPORT_EMPTY_ORIGIN_ALLOWED_PROPERTY_KEY = "internal.mongock.import.emptyOriginAllowed"; diff --git a/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/MongockImportChange.java b/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/MongockImportChange.java index 33a3454aa..2cdd278cf 100644 --- a/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/MongockImportChange.java +++ b/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/MongockImportChange.java @@ -23,7 +23,6 @@ import io.flamingock.internal.common.core.audit.AuditWriter; import io.flamingock.internal.common.core.error.FlamingockException; import io.flamingock.internal.common.core.pipeline.PipelineDescriptor; -import io.flamingock.internal.common.core.util.ConfigValueParser; import io.flamingock.internal.core.external.targets.TargetSystemManager; import io.flamingock.internal.core.external.targets.operations.TargetSystemOps; import io.flamingock.internal.core.external.targets.operations.TransactionalTargetSystemOps; @@ -35,6 +34,7 @@ import static io.flamingock.internal.common.core.audit.AuditReaderType.MONGOCK; import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_EMPTY_ORIGIN_ALLOWED_PROPERTY_KEY; +import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_SKIP_PROPERTY_KEY; /** * This ChangeUnit is intentionally not annotated with @Change, @Apply, or similar, @@ -48,7 +48,12 @@ public void importHistory(@Named("change.targetSystem.id") String targetSystemId @NonLockGuarded TargetSystemManager targetSystemManager, @NonLockGuarded AuditWriter auditWriter, @NonLockGuarded PipelineDescriptor pipelineDescriptor, - @Nullable @Named(MONGOCK_IMPORT_EMPTY_ORIGIN_ALLOWED_PROPERTY_KEY) String emptyOriginAllowed) { + @Nullable @Named(MONGOCK_IMPORT_EMPTY_ORIGIN_ALLOWED_PROPERTY_KEY) String emptyOriginAllowed, + @Nullable @Named(MONGOCK_IMPORT_SKIP_PROPERTY_KEY) String skipImport) { + if (resolveSkipImport(skipImport)) { + logger.info("Mongock audit log import skipped (skipImport=true). No audit entries will be migrated."); + return; + } logger.info("Starting audit log migration from Mongock to Flamingock community audit store"); AuditHistoryReader legacyHistoryReader = getAuditHistoryReader(targetSystemId, targetSystemManager); PipelineHelper pipelineHelper = new PipelineHelper(pipelineDescriptor); @@ -102,4 +107,15 @@ private boolean resolveEmptyOriginAllowed(String raw) { throw new FlamingockException("Invalid value for " + MONGOCK_IMPORT_EMPTY_ORIGIN_ALLOWED_PROPERTY_KEY + ": " + raw + " (expected \"true\" or \"false\" or empty)"); } + + private boolean resolveSkipImport(String raw) { + if (raw == null || raw.trim().isEmpty()) { + return false; // default behaviour + } + String v = raw.trim(); + if ("true".equalsIgnoreCase(v)) return true; + if ("false".equalsIgnoreCase(v)) return false; + throw new FlamingockException("Invalid value for " + MONGOCK_IMPORT_SKIP_PROPERTY_KEY + ": " + raw + + " (expected \"true\" or \"false\" or empty)"); + } } diff --git a/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/annotations/MongockSupport.java b/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/annotations/MongockSupport.java index 6e5feeee7..7eeedce6f 100644 --- a/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/annotations/MongockSupport.java +++ b/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/annotations/MongockSupport.java @@ -81,6 +81,20 @@ */ String targetSystem(); + /** + * Determines whether Mongock import should be skipped. + *

+ * Expected literal values are {@code "true"} or {@code "false"}. + *

+ * + *

+ * Default value is {@code "false"} (import enabled). + *

+ * + * @return {@code "true"} to skip import, {@code "false"} to process it + */ + String skipImport() default "false"; + /** * Defines the origin collection/table name where Mongock audit entries are stored. *

diff --git a/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/processor/MongockAnnotationProcessorPlugin.java b/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/processor/MongockAnnotationProcessorPlugin.java index 7c4f845fc..1df06f4ff 100644 --- a/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/processor/MongockAnnotationProcessorPlugin.java +++ b/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/processor/MongockAnnotationProcessorPlugin.java @@ -50,6 +50,7 @@ import java.util.stream.Stream; import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_EMPTY_ORIGIN_ALLOWED_PROPERTY_KEY; +import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_SKIP_PROPERTY_KEY; import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_ORIGIN_PROPERTY_KEY; @SuppressWarnings("deprecation") @@ -84,6 +85,7 @@ public Collection findAnnotatedChanges() { .flatMap(List::stream) .filter(Objects::nonNull) .collect(Collectors.toList()); + changes.add(getImporterChange(mongockTargetSystemId)); return changes; @@ -142,16 +144,23 @@ private void processConfigurationProperties(MongockSupport mongockSupport, Map Date: Fri, 6 Mar 2026 06:31:44 +0000 Subject: [PATCH 02/10] feat: added skipImport flag to MongockSupport annotation --- .../support/mongock/annotations/MongockSupport.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/annotations/MongockSupport.java b/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/annotations/MongockSupport.java index 7eeedce6f..22e12d71b 100644 --- a/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/annotations/MongockSupport.java +++ b/legacy/mongock-support/src/main/java/io/flamingock/support/mongock/annotations/MongockSupport.java @@ -88,12 +88,12 @@ *

* *

- * Default value is {@code "false"} (import enabled). + * If empty (default), it will be treated as {@code "false"}. *

* - * @return {@code "true"} to skip import, {@code "false"} to process it + * @return {@code "true"} to skip import, {@code "false"} to process it; empty treated as {@code "false"} */ - String skipImport() default "false"; + String skipImport() default ""; /** * Defines the origin collection/table name where Mongock audit entries are stored. From 43487649e76d48c8aa3bda3222af62606770d922 Mon Sep 17 00:00:00 2001 From: Oliver Santana Date: Mon, 9 Mar 2026 22:04:19 +0000 Subject: [PATCH 03/10] feat: added skipImport flag to MongockSupport annotation --- .../couchbase/CouchbaseImporterTest.java | 179 +++++++++++++++- .../dynamodb/DynamoDBImporterTest.java | 183 ++++++++++++++++ .../mongock/mongodb/MongoDBImporterTest.java | 198 ++++++++++++++++++ 3 files changed, 559 insertions(+), 1 deletion(-) diff --git a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java index 513e87d60..10bbfbca1 100644 --- a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java +++ b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java @@ -48,6 +48,7 @@ import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_EMPTY_ORIGIN_ALLOWED_PROPERTY_KEY; import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_ORIGIN_PROPERTY_KEY; +import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_SKIP_PROPERTY_KEY; import static io.flamingock.internal.util.constants.AuditEntryFieldConstants.KEY_CREATED_AT; import static io.flamingock.internal.util.constants.AuditEntryFieldConstants.KEY_STATE; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -352,6 +353,183 @@ void GIVEN_allMongockChangeUnitsAlreadyExecutedAndCustomOriginProvided_WHEN_migr assertEquals("APPLIED", auditLog.get(6).getString("state")); } + @Test + @DisplayName("GIVEN skip import flag with invalid value " + + "WHEN migrating to Flamingock Community" + + "THEN should throw exception") + void GIVEN_skipImportFlagWithInvalidValue_WHEN_migratingToFlamingockCommunity_THEN_shouldThrowException() { + + final String SKIP_IMPORT_VALUE = "invalid_value"; + + CouchbaseTargetSystem targetSystem = new CouchbaseTargetSystem("couchbase-target-system", cluster, FLAMINGOCK_BUCKET_NAME); + + Runner flamingock = FlamingockFactory.getCommunityBuilder() + .setAuditStore(CouchbaseAuditStore.from(targetSystem) + .withScopeName(FLAMINGOCK_SCOPE_NAME) + .withAuditRepositoryName(FLAMINGOCK_COLLECTION_NAME)) + .addTargetSystem(targetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + FlamingockException ex = assertThrows(FlamingockException.class, flamingock::run); + assertEquals("Invalid value for " + MONGOCK_IMPORT_SKIP_PROPERTY_KEY + ": " + SKIP_IMPORT_VALUE + + " (expected \"true\" or \"false\" or empty)", ex.getMessage()); + } + + @Test + @DisplayName("GIVEN all Mongock changeUnits already executed" + + "AND skip import flag enabled " + + "WHEN migrating to Flamingock Community" + + "THEN should not import any audit history entry " + + "AND execute the all mongock and flamingock changes") + void GIVEN_skipImportFlagEnabled_WHEN_migratingToFlamingockCommunity_THEN_shouldNotMigrateAnyAuditLog() { + + Collection originCollection = cluster.bucket(MONGOCK_BUCKET_NAME).scope(MONGOCK_SCOPE_NAME).collection(MONGOCK_COLLECTION_NAME); + + originCollection.upsert("mongock-change-1", createAuditObject("mongock-change-1")); + originCollection.upsert("mongock-change-2", createAuditObject("mongock-change-2")); + + final String SKIP_IMPORT_VALUE = "true"; + + CouchbaseTargetSystem targetSystem = new CouchbaseTargetSystem("couchbase-target-system", cluster, FLAMINGOCK_BUCKET_NAME); + + Runner flamingock = FlamingockFactory.getCommunityBuilder() + .setAuditStore(CouchbaseAuditStore.from(targetSystem) + .withScopeName(FLAMINGOCK_SCOPE_NAME) + .withAuditRepositoryName(FLAMINGOCK_COLLECTION_NAME)) + .addTargetSystem(targetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + flamingock.run(); + + List auditLog = getAuditLog(); + + assertEquals(8, auditLog.size()); + + assertEquals("migration-mongock-to-flamingock-community", auditLog.get(0).getString("changeId")); + assertEquals("STARTED", auditLog.get(0).getString("state")); + + assertEquals("migration-mongock-to-flamingock-community", auditLog.get(1).getString("changeId")); + assertEquals("APPLIED", auditLog.get(1).getString("state")); + + assertEquals("mongock-change-1", auditLog.get(2).getString("changeId")); + assertEquals("STARTED", auditLog.get(2).getString("state")); + + assertEquals("mongock-change-1", auditLog.get(3).getString("changeId")); + assertEquals("APPLIED", auditLog.get(3).getString("state")); + + assertEquals("mongock-change-2", auditLog.get(4).getString("changeId")); + assertEquals("STARTED", auditLog.get(4).getString("state")); + + assertEquals("mongock-change-2", auditLog.get(5).getString("changeId")); + assertEquals("APPLIED", auditLog.get(5).getString("state")); + + assertEquals("flamingock-change", auditLog.get(6).getString("changeId")); + assertEquals("STARTED", auditLog.get(6).getString("state")); + + assertEquals("flamingock-change", auditLog.get(7).getString("changeId")); + assertEquals("APPLIED", auditLog.get(7).getString("state")); + } + + @Test + @DisplayName("GIVEN all Mongock changeUnits already executed" + + "AND skip import flag disabled (explicit) " + + "WHEN migrating to Flamingock Community " + + "THEN should import the entire history " + + "AND execute the pending flamingock changes") + void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledExplicit_WHEN_migratingToFlamingockCommunity_THEN_shouldImportEntireHistory() { + Collection originCollection = cluster.bucket(MONGOCK_BUCKET_NAME).scope(MONGOCK_SCOPE_NAME).collection(MONGOCK_COLLECTION_NAME); + + originCollection.upsert("mongock-change-1", createAuditObject("mongock-change-1")); + originCollection.upsert("mongock-change-2", createAuditObject("mongock-change-2")); + + CouchbaseTargetSystem targetSystem = new CouchbaseTargetSystem("couchbase-target-system", cluster, FLAMINGOCK_BUCKET_NAME); + + final String SKIP_IMPORT_VALUE = "false"; + + Runner flamingock = FlamingockFactory.getCommunityBuilder() + .setAuditStore(CouchbaseAuditStore.from(targetSystem) + .withScopeName(FLAMINGOCK_SCOPE_NAME) + .withAuditRepositoryName(FLAMINGOCK_COLLECTION_NAME)) + .addTargetSystem(targetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + flamingock.run(); + + List auditLog = getAuditLog(); + + assertEquals(6, auditLog.size()); + + assertEquals("mongock-change-1", auditLog.get(0).getString("changeId")); + assertEquals("APPLIED", auditLog.get(0).getString("state")); + + assertEquals("mongock-change-2", auditLog.get(1).getString("changeId")); + assertEquals("APPLIED", auditLog.get(1).getString("state")); + + assertEquals("migration-mongock-to-flamingock-community", auditLog.get(2).getString("changeId")); + assertEquals("STARTED", auditLog.get(2).getString("state")); + + assertEquals("migration-mongock-to-flamingock-community", auditLog.get(3).getString("changeId")); + assertEquals("APPLIED", auditLog.get(3).getString("state")); + + assertEquals("flamingock-change", auditLog.get(4).getString("changeId")); + assertEquals("STARTED", auditLog.get(4).getString("state")); + + assertEquals("flamingock-change", auditLog.get(5).getString("changeId")); + assertEquals("APPLIED", auditLog.get(5).getString("state")); + } + + @Test + @DisplayName("GIVEN all Mongock changeUnits already executed" + + "AND skip import flag disabled (implicit) " + + "WHEN migrating to Flamingock Community " + + "THEN should import the entire history " + + "AND execute the pending flamingock changes") + void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledImplicit_WHEN_migratingToFlamingockCommunity_THEN_shouldImportEntireHistory() { + Collection originCollection = cluster.bucket(MONGOCK_BUCKET_NAME).scope(MONGOCK_SCOPE_NAME).collection(MONGOCK_COLLECTION_NAME); + + originCollection.upsert("mongock-change-1", createAuditObject("mongock-change-1")); + originCollection.upsert("mongock-change-2", createAuditObject("mongock-change-2")); + + CouchbaseTargetSystem targetSystem = new CouchbaseTargetSystem("couchbase-target-system", cluster, FLAMINGOCK_BUCKET_NAME); + + final String SKIP_IMPORT_VALUE = ""; + + Runner flamingock = FlamingockFactory.getCommunityBuilder() + .setAuditStore(CouchbaseAuditStore.from(targetSystem) + .withScopeName(FLAMINGOCK_SCOPE_NAME) + .withAuditRepositoryName(FLAMINGOCK_COLLECTION_NAME)) + .addTargetSystem(targetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + flamingock.run(); + + List auditLog = getAuditLog(); + + assertEquals(6, auditLog.size()); + + assertEquals("mongock-change-1", auditLog.get(0).getString("changeId")); + assertEquals("APPLIED", auditLog.get(0).getString("state")); + + assertEquals("mongock-change-2", auditLog.get(1).getString("changeId")); + assertEquals("APPLIED", auditLog.get(1).getString("state")); + + assertEquals("migration-mongock-to-flamingock-community", auditLog.get(2).getString("changeId")); + assertEquals("STARTED", auditLog.get(2).getString("state")); + + assertEquals("migration-mongock-to-flamingock-community", auditLog.get(3).getString("changeId")); + assertEquals("APPLIED", auditLog.get(3).getString("state")); + + assertEquals("flamingock-change", auditLog.get(4).getString("changeId")); + assertEquals("STARTED", auditLog.get(4).getString("state")); + + assertEquals("flamingock-change", auditLog.get(5).getString("changeId")); + assertEquals("APPLIED", auditLog.get(5).getString("state")); + } + private List getAuditLog() { return CouchbaseCollectionHelper.selectAllDocuments(cluster, FLAMINGOCK_BUCKET_NAME, FLAMINGOCK_SCOPE_NAME, FLAMINGOCK_COLLECTION_NAME) @@ -379,5 +557,4 @@ private static JsonObject createAuditObject(String value) { .put("_doctype", "mongockChangeEntry"); return doc; } - } diff --git a/legacy/mongock-importer-dynamodb/src/test/java/io/flamingock/importer/mongock/dynamodb/DynamoDBImporterTest.java b/legacy/mongock-importer-dynamodb/src/test/java/io/flamingock/importer/mongock/dynamodb/DynamoDBImporterTest.java index dc7214891..ca64a1a92 100644 --- a/legacy/mongock-importer-dynamodb/src/test/java/io/flamingock/importer/mongock/dynamodb/DynamoDBImporterTest.java +++ b/legacy/mongock-importer-dynamodb/src/test/java/io/flamingock/importer/mongock/dynamodb/DynamoDBImporterTest.java @@ -49,6 +49,7 @@ import static io.flamingock.internal.common.core.metadata.Constants.DEFAULT_MONGOCK_ORIGIN; import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_EMPTY_ORIGIN_ALLOWED_PROPERTY_KEY; import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_ORIGIN_PROPERTY_KEY; +import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_SKIP_PROPERTY_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -335,6 +336,188 @@ void GIVEN_allMongockChangeUnitsAlreadyExecutedAndCustomOriginProvided_WHEN_migr + // Validate actual table creation + assertTrue(client.listTables().tableNames().contains("users"), "Users table should exist"); + + // Verify table structure + DescribeTableResponse tableDescription = client.describeTable( + DescribeTableRequest.builder().tableName("users").build() + ); + assertEquals("email", tableDescription.table().keySchema().get(0).attributeName()); + assertEquals(KeyType.HASH, tableDescription.table().keySchema().get(0).keyType()); + } + + @Test + @DisplayName("GIVEN skip import flag with invalid value " + + "WHEN migrating to Flamingock Community" + + "THEN should throw exception") + void GIVEN_skipImportFlagWithInvalidValue_WHEN_migratingToFlamingockCommunity_THEN_shouldThrowException() { + // Setup Mongock entries + + DynamoDBTargetSystem dynamodbTargetSystem = new DynamoDBTargetSystem("dynamodb-target-system", client); + + final String SKIP_IMPORT_VALUE = "invalid_value"; + + Runner flamingock = testKit.createBuilder() + .addTargetSystem(dynamodbTargetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + FlamingockException ex = assertThrows(FlamingockException.class, flamingock::run); + assertEquals("Invalid value for " + MONGOCK_IMPORT_SKIP_PROPERTY_KEY + ": " + SKIP_IMPORT_VALUE + + " (expected \"true\" or \"false\" or empty)", ex.getMessage()); + + } + + @Test + @DisplayName("GIVEN all Mongock changeUnits already executed" + + "AND skip import flag enabled " + + "WHEN migrating to Flamingock Community" + + "THEN should not import any audit history entry " + + "AND execute the all mongock and flamingock changes") + void GIVEN_skipImportFlagEnabled_WHEN_migratingToFlamingockCommunity_THEN_shouldNotMigrateAnyAuditLog() { + + // Setup Mongock entries + mongockTestHelper.setupBasicScenario(); + + DynamoDBTargetSystem dynamodbTargetSystem = new DynamoDBTargetSystem("dynamodb-target-system", client); + + final String SKIP_IMPORT_VALUE = "true"; + + Runner flamingock = testKit.createBuilder() + .addTargetSystem(dynamodbTargetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + flamingock.run(); + + // Verify audit sequence: 8 total entries as shown in actual execution + auditHelper.verifyAuditSequenceStrict( + // System stage - actual system importer change + STARTED("migration-mongock-to-flamingock-community"), + APPLIED("migration-mongock-to-flamingock-community"), + + // Legacy changes + STARTED("mongock-change-1"), + APPLIED("mongock-change-1"), + STARTED("mongock-change-2"), + APPLIED("mongock-change-2"), + + // Application stage - new changes created by templates + STARTED("create-users-table"), + APPLIED("create-users-table") + ); + + + + // Validate actual table creation + assertTrue(client.listTables().tableNames().contains("users"), "Users table should exist"); + + // Verify table structure + DescribeTableResponse tableDescription = client.describeTable( + DescribeTableRequest.builder().tableName("users").build() + ); + assertEquals("email", tableDescription.table().keySchema().get(0).attributeName()); + assertEquals(KeyType.HASH, tableDescription.table().keySchema().get(0).keyType()); + } + + @Test + @DisplayName("GIVEN all Mongock changeUnits already executed" + + "AND skip import flag disabled (explicit) " + + "WHEN migrating to Flamingock Community " + + "THEN should import the entire history " + + "AND execute the pending flamingock changes") + void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledExplicit_WHEN_migratingToFlamingockCommunity_THEN_shouldImportEntireHistory() { + + // Setup Mongock entries + mongockTestHelper.setupBasicScenario(); + + DynamoDBTargetSystem dynamodbTargetSystem = new DynamoDBTargetSystem("dynamodb-target-system", client); + + final String SKIP_IMPORT_VALUE = "false"; + + Runner flamingock = testKit.createBuilder() + .addTargetSystem(dynamodbTargetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + flamingock.run(); + + // Verify audit sequence: 9 total entries as shown in actual execution + // Legacy imports only show APPLIED (imported from Mongock), new changes show STARTED+APPLIED + auditHelper.verifyAuditSequenceStrict( + // Legacy imports from Mongock (APPLIED only - no STARTED for imported changes) + APPLIED("system-change-00001_before"), + APPLIED("system-change-00001"), + APPLIED("mongock-change-1_before"), + APPLIED("mongock-change-1"), + APPLIED("mongock-change-2"), + + // System stage - actual system importer change + STARTED("migration-mongock-to-flamingock-community"), + APPLIED("migration-mongock-to-flamingock-community"), + + // Application stage - new changes created by templates + STARTED("create-users-table"), + APPLIED("create-users-table") + ); + + + + // Validate actual table creation + assertTrue(client.listTables().tableNames().contains("users"), "Users table should exist"); + + // Verify table structure + DescribeTableResponse tableDescription = client.describeTable( + DescribeTableRequest.builder().tableName("users").build() + ); + assertEquals("email", tableDescription.table().keySchema().get(0).attributeName()); + assertEquals(KeyType.HASH, tableDescription.table().keySchema().get(0).keyType()); + } + + @Test + @DisplayName("GIVEN all Mongock changeUnits already executed" + + "AND skip import flag disabled (implicit) " + + "WHEN migrating to Flamingock Community " + + "THEN should import the entire history " + + "AND execute the pending flamingock changes") + void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledImplicit_WHEN_migratingToFlamingockCommunity_THEN_shouldImportEntireHistory() { + + // Setup Mongock entries + mongockTestHelper.setupBasicScenario(); + + DynamoDBTargetSystem dynamodbTargetSystem = new DynamoDBTargetSystem("dynamodb-target-system", client); + + final String SKIP_IMPORT_VALUE = ""; + + Runner flamingock = testKit.createBuilder() + .addTargetSystem(dynamodbTargetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + flamingock.run(); + + // Verify audit sequence: 9 total entries as shown in actual execution + // Legacy imports only show APPLIED (imported from Mongock), new changes show STARTED+APPLIED + auditHelper.verifyAuditSequenceStrict( + // Legacy imports from Mongock (APPLIED only - no STARTED for imported changes) + APPLIED("system-change-00001_before"), + APPLIED("system-change-00001"), + APPLIED("mongock-change-1_before"), + APPLIED("mongock-change-1"), + APPLIED("mongock-change-2"), + + // System stage - actual system importer change + STARTED("migration-mongock-to-flamingock-community"), + APPLIED("migration-mongock-to-flamingock-community"), + + // Application stage - new changes created by templates + STARTED("create-users-table"), + APPLIED("create-users-table") + ); + + + // Validate actual table creation assertTrue(client.listTables().tableNames().contains("users"), "Users table should exist"); diff --git a/legacy/mongock-importer-mongodb/src/test/java/io/flamingock/importer/mongock/mongodb/MongoDBImporterTest.java b/legacy/mongock-importer-mongodb/src/test/java/io/flamingock/importer/mongock/mongodb/MongoDBImporterTest.java index a14e0cf49..b0b6f1cc5 100644 --- a/legacy/mongock-importer-mongodb/src/test/java/io/flamingock/importer/mongock/mongodb/MongoDBImporterTest.java +++ b/legacy/mongock-importer-mongodb/src/test/java/io/flamingock/importer/mongock/mongodb/MongoDBImporterTest.java @@ -49,6 +49,7 @@ import static io.flamingock.internal.common.core.metadata.Constants.DEFAULT_MONGOCK_ORIGIN; import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_EMPTY_ORIGIN_ALLOWED_PROPERTY_KEY; import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_ORIGIN_PROPERTY_KEY; +import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_SKIP_PROPERTY_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -353,6 +354,203 @@ void GIVEN_allMongockChangeUnitsAlreadyExecutedAndCustomOriginProvidedByLiteralV + // Validate actual change + List users = database.getCollection("users") + .find() + .into(new ArrayList<>()); + + assertEquals(2, users.size()); + Assertions.assertEquals("Admin", users.get(0).getString("name")); + Assertions.assertEquals("admin@company.com", users.get(0).getString("email")); + Assertions.assertEquals("superuser", users.get(0).getList("roles", String.class).get(0)); + + Assertions.assertEquals("Backup", users.get(1).getString("name")); + Assertions.assertEquals("backup@company.com", users.get(1).getString("email")); + Assertions.assertEquals("readonly", users.get(1).getList("roles", String.class).get(0)); + } + + @Test + @DisplayName("GIVEN skip import flag with invalid value " + + "WHEN migrating to Flamingock Community" + + "THEN should throw exception") + void GIVEN_skipImportFlagWithInvalidValue_WHEN_migratingToFlamingockCommunity_THEN_shouldThrowException() { + // Setup Mongock entries + + MongoDBSyncTargetSystem mongodbTargetSystem = new MongoDBSyncTargetSystem("mongodb-target-system", mongoClient, DATABASE_NAME); + + final String SKIP_IMPORT_VALUE = "invalid_value"; + + Runner flamingock = testKit.createBuilder() + .addTargetSystem(mongodbTargetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + FlamingockException ex = assertThrows(FlamingockException.class, flamingock::run); + assertEquals("Invalid value for " + MONGOCK_IMPORT_SKIP_PROPERTY_KEY + ": " + SKIP_IMPORT_VALUE + + " (expected \"true\" or \"false\" or empty)", ex.getMessage()); + } + + + @Test + @DisplayName("GIVEN all Mongock changeUnits already executed" + + "AND skip import flag enabled " + + "WHEN migrating to Flamingock Community" + + "THEN should not import any audit history entry " + + "AND execute the all mongock and flamingock changes") + void GIVEN_skipImportFlagEnabled_WHEN_migratingToFlamingockCommunity_THEN_shouldNotMigrateAnyAuditLog() { + + // Setup Mongock entries + mongockTestHelper.setupBasicScenario(); + + MongoDBSyncTargetSystem mongodbTargetSystem = new MongoDBSyncTargetSystem("mongodb-target-system", mongoClient, DATABASE_NAME); + + final String SKIP_IMPORT_VALUE = "true"; + + Runner flamingock = testKit.createBuilder() + .addTargetSystem(mongodbTargetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + flamingock.run(); + + // Verify audit sequence: 10 total entries as shown in actual execution + auditHelper.verifyAuditSequenceStrict( + // System stage - actual system importer change + STARTED("migration-mongock-to-flamingock-community"), + APPLIED("migration-mongock-to-flamingock-community"), + + // Legacy changes + STARTED("mongock-change-1"), + APPLIED("mongock-change-1"), + STARTED("mongock-change-2"), + APPLIED("mongock-change-2"), + + // Application stage - new changes created by templates + STARTED("create-users-collection-with-index"), + APPLIED("create-users-collection-with-index"), + STARTED("seed-users"), + APPLIED("seed-users") + ); + + + // Validate actual change + List users = database.getCollection("users") + .find() + .into(new ArrayList<>()); + + assertEquals(2, users.size()); + Assertions.assertEquals("Admin", users.get(0).getString("name")); + Assertions.assertEquals("admin@company.com", users.get(0).getString("email")); + Assertions.assertEquals("superuser", users.get(0).getList("roles", String.class).get(0)); + + Assertions.assertEquals("Backup", users.get(1).getString("name")); + Assertions.assertEquals("backup@company.com", users.get(1).getString("email")); + Assertions.assertEquals("readonly", users.get(1).getList("roles", String.class).get(0)); + } + + @Test + @DisplayName("GIVEN all Mongock changeUnits already executed" + + "AND skip import flag disabled (explicit) " + + "WHEN migrating to Flamingock Community " + + "THEN should import the entire history " + + "AND execute the pending flamingock changes") + void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledExplicit_WHEN_migratingToFlamingockCommunity_THEN_shouldImportEntireHistory() { + + // Setup Mongock entries + mongockTestHelper.setupBasicScenario(); + + MongoDBSyncTargetSystem mongodbTargetSystem = new MongoDBSyncTargetSystem("mongodb-target-system", mongoClient, DATABASE_NAME); + + final String SKIP_IMPORT_VALUE = "false"; + + Runner flamingock = testKit.createBuilder() + .addTargetSystem(mongodbTargetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + flamingock.run(); + + // Verify audit sequence: 11 total entries as shown in actual execution + // Legacy imports only show APPLIED (imported from Mongock), new changes show STARTED+APPLIED + auditHelper.verifyAuditSequenceStrict( + // Legacy imports from Mongock (APPLIED only - no STARTED for imported changes) + APPLIED("system-change-00001_before"), + APPLIED("system-change-00001"), + APPLIED("mongock-change-1_before"), + APPLIED("mongock-change-1"), + APPLIED("mongock-change-2"), + + // System stage - actual system importer change + STARTED("migration-mongock-to-flamingock-community"), + APPLIED("migration-mongock-to-flamingock-community"), + + // Application stage - new changes created by templates + STARTED("create-users-collection-with-index"), + APPLIED("create-users-collection-with-index"), + STARTED("seed-users"), + APPLIED("seed-users") + ); + + + // Validate actual change + List users = database.getCollection("users") + .find() + .into(new ArrayList<>()); + + assertEquals(2, users.size()); + Assertions.assertEquals("Admin", users.get(0).getString("name")); + Assertions.assertEquals("admin@company.com", users.get(0).getString("email")); + Assertions.assertEquals("superuser", users.get(0).getList("roles", String.class).get(0)); + + Assertions.assertEquals("Backup", users.get(1).getString("name")); + Assertions.assertEquals("backup@company.com", users.get(1).getString("email")); + Assertions.assertEquals("readonly", users.get(1).getList("roles", String.class).get(0)); + } + + @Test + @DisplayName("GIVEN all Mongock changeUnits already executed" + + "AND skip import flag disabled (implicit) " + + "WHEN migrating to Flamingock Community " + + "THEN should import the entire history " + + "AND execute the pending flamingock changes") + void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledImplicit_WHEN_migratingToFlamingockCommunity_THEN_shouldImportEntireHistory() { + + // Setup Mongock entries + mongockTestHelper.setupBasicScenario(); + + MongoDBSyncTargetSystem mongodbTargetSystem = new MongoDBSyncTargetSystem("mongodb-target-system", mongoClient, DATABASE_NAME); + + final String SKIP_IMPORT_VALUE = ""; + + Runner flamingock = testKit.createBuilder() + .addTargetSystem(mongodbTargetSystem) + .setProperty(MONGOCK_IMPORT_SKIP_PROPERTY_KEY, SKIP_IMPORT_VALUE) // only allows empty / true / false + .build(); + + flamingock.run(); + + // Verify audit sequence: 11 total entries as shown in actual execution + // Legacy imports only show APPLIED (imported from Mongock), new changes show STARTED+APPLIED + auditHelper.verifyAuditSequenceStrict( + // Legacy imports from Mongock (APPLIED only - no STARTED for imported changes) + APPLIED("system-change-00001_before"), + APPLIED("system-change-00001"), + APPLIED("mongock-change-1_before"), + APPLIED("mongock-change-1"), + APPLIED("mongock-change-2"), + + // System stage - actual system importer change + STARTED("migration-mongock-to-flamingock-community"), + APPLIED("migration-mongock-to-flamingock-community"), + + // Application stage - new changes created by templates + STARTED("create-users-collection-with-index"), + APPLIED("create-users-collection-with-index"), + STARTED("seed-users"), + APPLIED("seed-users") + ); + + // Validate actual change List users = database.getCollection("users") .find() From 3aa770bb53e8bb0a557de025452015dbda45d3a3 Mon Sep 17 00:00:00 2001 From: Oliver Santana Date: Mon, 9 Mar 2026 23:43:13 +0000 Subject: [PATCH 04/10] feat: added skipImport flag to MongockSupport annotation --- .../importer/mongock/couchbase/CouchbaseImporterTest.java | 6 +++--- .../importer/mongock/dynamodb/DynamoDBImporterTest.java | 6 +++--- .../importer/mongock/mongodb/MongoDBImporterTest.java | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java index 10bbfbca1..2b8a93c35 100644 --- a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java +++ b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java @@ -377,7 +377,7 @@ void GIVEN_skipImportFlagWithInvalidValue_WHEN_migratingToFlamingockCommunity_TH } @Test - @DisplayName("GIVEN all Mongock changeUnits already executed" + + @DisplayName("GIVEN all Mongock changeUnits already executed " + "AND skip import flag enabled " + "WHEN migrating to Flamingock Community" + "THEN should not import any audit history entry " + @@ -433,7 +433,7 @@ void GIVEN_skipImportFlagEnabled_WHEN_migratingToFlamingockCommunity_THEN_should } @Test - @DisplayName("GIVEN all Mongock changeUnits already executed" + + @DisplayName("GIVEN all Mongock changeUnits already executed " + "AND skip import flag disabled (explicit) " + "WHEN migrating to Flamingock Community " + "THEN should import the entire history " + @@ -482,7 +482,7 @@ void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledExplicit } @Test - @DisplayName("GIVEN all Mongock changeUnits already executed" + + @DisplayName("GIVEN all Mongock changeUnits already executed " + "AND skip import flag disabled (implicit) " + "WHEN migrating to Flamingock Community " + "THEN should import the entire history " + diff --git a/legacy/mongock-importer-dynamodb/src/test/java/io/flamingock/importer/mongock/dynamodb/DynamoDBImporterTest.java b/legacy/mongock-importer-dynamodb/src/test/java/io/flamingock/importer/mongock/dynamodb/DynamoDBImporterTest.java index ca64a1a92..08388f080 100644 --- a/legacy/mongock-importer-dynamodb/src/test/java/io/flamingock/importer/mongock/dynamodb/DynamoDBImporterTest.java +++ b/legacy/mongock-importer-dynamodb/src/test/java/io/flamingock/importer/mongock/dynamodb/DynamoDBImporterTest.java @@ -370,7 +370,7 @@ void GIVEN_skipImportFlagWithInvalidValue_WHEN_migratingToFlamingockCommunity_TH } @Test - @DisplayName("GIVEN all Mongock changeUnits already executed" + + @DisplayName("GIVEN all Mongock changeUnits already executed " + "AND skip import flag enabled " + "WHEN migrating to Flamingock Community" + "THEN should not import any audit history entry " + @@ -422,7 +422,7 @@ void GIVEN_skipImportFlagEnabled_WHEN_migratingToFlamingockCommunity_THEN_should } @Test - @DisplayName("GIVEN all Mongock changeUnits already executed" + + @DisplayName("GIVEN all Mongock changeUnits already executed " + "AND skip import flag disabled (explicit) " + "WHEN migrating to Flamingock Community " + "THEN should import the entire history " + @@ -476,7 +476,7 @@ void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledExplicit } @Test - @DisplayName("GIVEN all Mongock changeUnits already executed" + + @DisplayName("GIVEN all Mongock changeUnits already executed " + "AND skip import flag disabled (implicit) " + "WHEN migrating to Flamingock Community " + "THEN should import the entire history " + diff --git a/legacy/mongock-importer-mongodb/src/test/java/io/flamingock/importer/mongock/mongodb/MongoDBImporterTest.java b/legacy/mongock-importer-mongodb/src/test/java/io/flamingock/importer/mongock/mongodb/MongoDBImporterTest.java index b0b6f1cc5..d369afecf 100644 --- a/legacy/mongock-importer-mongodb/src/test/java/io/flamingock/importer/mongock/mongodb/MongoDBImporterTest.java +++ b/legacy/mongock-importer-mongodb/src/test/java/io/flamingock/importer/mongock/mongodb/MongoDBImporterTest.java @@ -392,7 +392,7 @@ void GIVEN_skipImportFlagWithInvalidValue_WHEN_migratingToFlamingockCommunity_TH @Test - @DisplayName("GIVEN all Mongock changeUnits already executed" + + @DisplayName("GIVEN all Mongock changeUnits already executed " + "AND skip import flag enabled " + "WHEN migrating to Flamingock Community" + "THEN should not import any audit history entry " + @@ -449,7 +449,7 @@ void GIVEN_skipImportFlagEnabled_WHEN_migratingToFlamingockCommunity_THEN_should } @Test - @DisplayName("GIVEN all Mongock changeUnits already executed" + + @DisplayName("GIVEN all Mongock changeUnits already executed " + "AND skip import flag disabled (explicit) " + "WHEN migrating to Flamingock Community " + "THEN should import the entire history " + @@ -508,7 +508,7 @@ void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledExplicit } @Test - @DisplayName("GIVEN all Mongock changeUnits already executed" + + @DisplayName("GIVEN all Mongock changeUnits already executed " + "AND skip import flag disabled (implicit) " + "WHEN migrating to Flamingock Community " + "THEN should import the entire history " + From b0e71dfc151a3cd6820b3d367cf69177b93f466b Mon Sep 17 00:00:00 2001 From: Oliver Santana Date: Wed, 11 Mar 2026 07:20:00 +0000 Subject: [PATCH 05/10] feat: added skipImport flag to MongockSupport annotation --- .github/workflows/build.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 91e9fb4d8..3fa7a32f3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ jobs: steps: - name: Checkout project - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Java uses: graalvm/setup-graalvm@v1 @@ -19,3 +19,12 @@ jobs: run: | ./gradlew clean build \ -Psql.test.dialects=mysql + + - name: Upload test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-reports + path: | + **/build/reports/tests/** + **/build/test-results/** From ee50e8e0662cd717cfcaa089eaeadb5ae7f00e9e Mon Sep 17 00:00:00 2001 From: Oliver Santana Date: Wed, 11 Mar 2026 07:37:16 +0000 Subject: [PATCH 06/10] feat: added skipImport flag to MongockSupport annotation --- .../importer/mongock/couchbase/CouchbaseImporterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java index 2b8a93c35..3f61e5368 100644 --- a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java +++ b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java @@ -509,7 +509,7 @@ void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledImplicit List auditLog = getAuditLog(); - assertEquals(6, auditLog.size()); + //assertEquals(6, auditLog.size()); assertEquals("mongock-change-1", auditLog.get(0).getString("changeId")); assertEquals("APPLIED", auditLog.get(0).getString("state")); From 80c54890fad88cf44d8ee81ed57e387a7a56a9fe Mon Sep 17 00:00:00 2001 From: Oliver Santana Date: Wed, 11 Mar 2026 07:56:22 +0000 Subject: [PATCH 07/10] feat: added skipImport flag to MongockSupport annotation --- .../mongock/couchbase/CouchbaseImporterTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java index 3f61e5368..68f5e7163 100644 --- a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java +++ b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java @@ -54,11 +54,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -@Testcontainers +/*@Testcontainers @MongockSupport(targetSystem = "couchbase-target-system") -@EnableFlamingock(stages = {@Stage(location = "io.flamingock.importer.mongock.couchbase.changes")}) +@EnableFlamingock(stages = {@Stage(location = "io.flamingock.importer.mongock.couchbase.changes")})*/ public class CouchbaseImporterTest { - +/* public static final String FLAMINGOCK_BUCKET_NAME = "test"; public static final String FLAMINGOCK_SCOPE_NAME = "flamingock"; public static final String FLAMINGOCK_COLLECTION_NAME = CommunityPersistenceConstants.DEFAULT_AUDIT_STORE_NAME; @@ -509,7 +509,7 @@ void GIVEN_allMongockChangeUnitsAlreadyExecutedAndSkipImportFlagDisabledImplicit List auditLog = getAuditLog(); - //assertEquals(6, auditLog.size()); + assertEquals(6, auditLog.size()); assertEquals("mongock-change-1", auditLog.get(0).getString("changeId")); assertEquals("APPLIED", auditLog.get(0).getString("state")); @@ -556,5 +556,5 @@ private static JsonObject createAuditObject(String value) { .put("systemChange", true) .put("_doctype", "mongockChangeEntry"); return doc; - } + }*/ } From 65168e600248950a02d0821326d380991bc86022 Mon Sep 17 00:00:00 2001 From: Oliver Santana Date: Wed, 11 Mar 2026 08:08:05 +0000 Subject: [PATCH 08/10] feat: added skipImport flag to MongockSupport annotation --- .../importer/mongock/couchbase/CouchbaseImporterTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java index 68f5e7163..94dd9e7ce 100644 --- a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java +++ b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java @@ -54,9 +54,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -/*@Testcontainers +/*@Testcontainers*/ @MongockSupport(targetSystem = "couchbase-target-system") -@EnableFlamingock(stages = {@Stage(location = "io.flamingock.importer.mongock.couchbase.changes")})*/ +@EnableFlamingock(stages = {@Stage(location = "io.flamingock.importer.mongock.couchbase.changes")}) public class CouchbaseImporterTest { /* public static final String FLAMINGOCK_BUCKET_NAME = "test"; From 88a4ec8c7625672f491b3a3e89f215123dced44e Mon Sep 17 00:00:00 2001 From: Oliver Santana Date: Wed, 11 Mar 2026 09:10:45 +0000 Subject: [PATCH 09/10] feat: added skipImport flag to MongockSupport annotation --- .../couchbase/CouchbaseImporterTest.java | 29 ++++++++----- .../couchbase/CouchbaseCollectionHelper.java | 41 ++++++++++++++++++- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java index 94dd9e7ce..6d6ffc035 100644 --- a/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java +++ b/legacy/mongock-importer-couchbase/src/test/java/io/flamingock/importer/mongock/couchbase/CouchbaseImporterTest.java @@ -54,11 +54,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -/*@Testcontainers*/ +@Testcontainers @MongockSupport(targetSystem = "couchbase-target-system") @EnableFlamingock(stages = {@Stage(location = "io.flamingock.importer.mongock.couchbase.changes")}) public class CouchbaseImporterTest { -/* + public static final String FLAMINGOCK_BUCKET_NAME = "test"; public static final String FLAMINGOCK_SCOPE_NAME = "flamingock"; public static final String FLAMINGOCK_COLLECTION_NAME = CommunityPersistenceConstants.DEFAULT_AUDIT_STORE_NAME; @@ -67,6 +67,9 @@ public class CouchbaseImporterTest { public static final String MONGOCK_SCOPE_NAME = CollectionIdentifier.DEFAULT_SCOPE; public static final String MONGOCK_COLLECTION_NAME = CollectionIdentifier.DEFAULT_COLLECTION; + public static final String CUSTOM_MONGOCK_ORIGIN_SCOPE = "mongockCustomScope"; + public static final String CUSTOM_MONGOCK_ORIGIN_COLLECTION = "mongockCustomOriginCollection"; + @Container static final CouchbaseContainer couchbaseContainer = new CouchbaseContainer("couchbase/server:7.2.4") @@ -102,7 +105,15 @@ static void setupAll() { @AfterEach void cleanUp() { CouchbaseCollectionHelper.deleteAllDocuments(cluster, FLAMINGOCK_BUCKET_NAME, FLAMINGOCK_SCOPE_NAME, FLAMINGOCK_COLLECTION_NAME); + CouchbaseCollectionHelper.waitUntilEmpty(cluster, FLAMINGOCK_BUCKET_NAME, FLAMINGOCK_SCOPE_NAME, FLAMINGOCK_COLLECTION_NAME, Duration.ofSeconds(10)); + CouchbaseCollectionHelper.deleteAllDocuments(cluster, MONGOCK_BUCKET_NAME, MONGOCK_SCOPE_NAME, MONGOCK_COLLECTION_NAME); + CouchbaseCollectionHelper.waitUntilEmpty(cluster, MONGOCK_BUCKET_NAME, MONGOCK_SCOPE_NAME, MONGOCK_COLLECTION_NAME, Duration.ofSeconds(10)); + + if (CouchbaseCollectionHelper.collectionExists(cluster, MONGOCK_BUCKET_NAME, CUSTOM_MONGOCK_ORIGIN_SCOPE, CUSTOM_MONGOCK_ORIGIN_COLLECTION)) { + CouchbaseCollectionHelper.deleteAllDocuments(cluster, MONGOCK_BUCKET_NAME, CUSTOM_MONGOCK_ORIGIN_SCOPE, CUSTOM_MONGOCK_ORIGIN_COLLECTION); + CouchbaseCollectionHelper.waitUntilEmpty(cluster, MONGOCK_BUCKET_NAME, CUSTOM_MONGOCK_ORIGIN_SCOPE, CUSTOM_MONGOCK_ORIGIN_COLLECTION, Duration.ofSeconds(10)); + } } @Test @@ -301,15 +312,13 @@ void GIVEN_mongockAuditHistoryEmptyAndFailIfEmptyOriginDisabled_WHEN_migratingTo "AND execute the pending flamingock changes") void GIVEN_allMongockChangeUnitsAlreadyExecutedAndCustomOriginProvided_WHEN_migratingToFlamingockCommunity_THEN_shouldImportEntireHistory() { // Setup Mongock entries - final String customMongockOriginScope = "mongockCustomScope"; - final String customMongockOriginCollection = "mongockCustomOriginCollection"; - final String customMongockOrigin = String.format("%s.%s", customMongockOriginScope, customMongockOriginCollection); + final String customMongockOrigin = String.format("%s.%s", CUSTOM_MONGOCK_ORIGIN_SCOPE, CUSTOM_MONGOCK_ORIGIN_COLLECTION); - CouchbaseCollectionHelper.createScopeIfNotExists(cluster, MONGOCK_BUCKET_NAME, customMongockOriginScope); - CouchbaseCollectionHelper.createCollectionIfNotExists(cluster, MONGOCK_BUCKET_NAME, customMongockOriginScope, customMongockOriginCollection); - CouchbaseCollectionHelper.createPrimaryIndexIfNotExists(cluster, MONGOCK_BUCKET_NAME, customMongockOriginScope, customMongockOriginCollection); + CouchbaseCollectionHelper.createScopeIfNotExists(cluster, MONGOCK_BUCKET_NAME, CUSTOM_MONGOCK_ORIGIN_SCOPE); + CouchbaseCollectionHelper.createCollectionIfNotExists(cluster, MONGOCK_BUCKET_NAME, CUSTOM_MONGOCK_ORIGIN_SCOPE, CUSTOM_MONGOCK_ORIGIN_COLLECTION); + CouchbaseCollectionHelper.createPrimaryIndexIfNotExists(cluster, MONGOCK_BUCKET_NAME, CUSTOM_MONGOCK_ORIGIN_SCOPE, CUSTOM_MONGOCK_ORIGIN_COLLECTION); - Collection originCollection = cluster.bucket(MONGOCK_BUCKET_NAME).scope(customMongockOriginScope).collection(customMongockOriginCollection); + Collection originCollection = cluster.bucket(MONGOCK_BUCKET_NAME).scope(CUSTOM_MONGOCK_ORIGIN_SCOPE).collection(CUSTOM_MONGOCK_ORIGIN_COLLECTION); originCollection.upsert("mongock-change-1", createAuditObject("mongock-change-1")); @@ -556,5 +565,5 @@ private static JsonObject createAuditObject(String value) { .put("systemChange", true) .put("_doctype", "mongockChangeEntry"); return doc; - }*/ + } } diff --git a/utils/couchbase-util/src/main/java/io/flamingock/internal/common/couchbase/CouchbaseCollectionHelper.java b/utils/couchbase-util/src/main/java/io/flamingock/internal/common/couchbase/CouchbaseCollectionHelper.java index 7e0be42bf..0ede9234a 100644 --- a/utils/couchbase-util/src/main/java/io/flamingock/internal/common/couchbase/CouchbaseCollectionHelper.java +++ b/utils/couchbase-util/src/main/java/io/flamingock/internal/common/couchbase/CouchbaseCollectionHelper.java @@ -37,7 +37,7 @@ public final class CouchbaseCollectionHelper { private final static String KEYSPACE_TEMPLATE = "`%s`.`%s`.`%s`"; - private final static String SELECT_COUNT_QUERY_TEMPLATE = "SELECT COUNT(*) FROM `%s`.`%s`.`%s`"; + private final static String SELECT_COUNT_QUERY_TEMPLATE = "SELECT COUNT(*) as cnt FROM `%s`.`%s`.`%s`"; private final static String SELECT_ALL_QUERY_TEMPLATE = "SELECT %s.* FROM `%s`.`%s`.`%s`"; private final static String DELETE_ALL_QUERY_TEMPLATE = "DELETE FROM `%s`.`%s`.`%s`"; private final static String CREATE_PRIMARY_INDEX_TEMPLATE = "CREATE PRIMARY INDEX IF NOT EXISTS ON `%s`.`%s`.`%s`"; @@ -173,4 +173,43 @@ public static void dropPrimaryIndexIfExists(Cluster cluster, String bucketName, public static void dropIndexIfExists(Cluster cluster, String bucketName, String scopeName, String collectionName, String indexName) { cluster.query(String.format(DROP_INDEX_TEMPLATE, indexName, bucketName, scopeName, collectionName)); } + + public static void waitUntilEmpty( + Cluster cluster, + String bucketName, + String scopeName, + String collectionName, + Duration timeout + ) { + long deadline = System.nanoTime() + timeout.toNanos(); + + while (System.nanoTime() < deadline) { + String countQuery = String.format(SELECT_COUNT_QUERY_TEMPLATE, bucketName, scopeName, collectionName); + + List rows = cluster.query(countQuery).rowsAsObject(); + long count = rows.isEmpty() ? 0L : rows.get(0).getLong("cnt"); + + if (count == 0L) { + return; + } + + try { + Thread.sleep(200); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException( + "Interrupted while waiting for collection cleanup", + e + ); + } + } + + throw new IllegalStateException(String.format( + "Timeout waiting for collection %s.%s.%s to be empty after %s", + bucketName, + scopeName, + collectionName, + timeout + )); + } } From 33ee5d71197cb401d5bcd7d1f542321b828781f1 Mon Sep 17 00:00:00 2001 From: davidfrigolet Date: Wed, 11 Mar 2026 10:53:44 +0000 Subject: [PATCH 10/10] fix: add scan consistency REQUEST_PLUS in CouchbaseCollectionHelper --- .../common/couchbase/CouchbaseCollectionHelper.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/couchbase-util/src/main/java/io/flamingock/internal/common/couchbase/CouchbaseCollectionHelper.java b/utils/couchbase-util/src/main/java/io/flamingock/internal/common/couchbase/CouchbaseCollectionHelper.java index 0ede9234a..8744a27b0 100644 --- a/utils/couchbase-util/src/main/java/io/flamingock/internal/common/couchbase/CouchbaseCollectionHelper.java +++ b/utils/couchbase-util/src/main/java/io/flamingock/internal/common/couchbase/CouchbaseCollectionHelper.java @@ -159,7 +159,8 @@ public static List selectAllDocuments(Cluster cluster, String bucket } public static void deleteAllDocuments(Cluster cluster, String bucketName, String scopeName, String collectionName) { - cluster.query(String.format(DELETE_ALL_QUERY_TEMPLATE, bucketName, scopeName, collectionName)); + cluster.query(String.format(DELETE_ALL_QUERY_TEMPLATE, bucketName, scopeName, collectionName), + QueryOptions.queryOptions().scanConsistency(QueryScanConsistency.REQUEST_PLUS)); } public static void createPrimaryIndexIfNotExists(Cluster cluster, String bucketName, String scopeName, String collectionName) { @@ -186,7 +187,8 @@ public static void waitUntilEmpty( while (System.nanoTime() < deadline) { String countQuery = String.format(SELECT_COUNT_QUERY_TEMPLATE, bucketName, scopeName, collectionName); - List rows = cluster.query(countQuery).rowsAsObject(); + List rows = cluster.query(countQuery, + QueryOptions.queryOptions().scanConsistency(QueryScanConsistency.REQUEST_PLUS)).rowsAsObject(); long count = rows.isEmpty() ? 0L : rows.get(0).getLong("cnt"); if (count == 0L) {