Skip to content

Commit 7539571

Browse files
committed
feat: support import from Mongock v4 MongoDB origin
1 parent 8c2290e commit 7539571

3 files changed

Lines changed: 132 additions & 13 deletions

File tree

legacy/mongock-importer-mongodb/src/main/java/io/flamingock/importer/mongock/mongodb/MongockAuditEntry.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ public MongockAuditEntry(String executionId,
5656
this.author = author;
5757
this.timestamp = timestamp;
5858
this.state = MongockAuditEntry.MongockChangeState.valueOf(state);
59-
this.type = MongockChangeType.valueOf(type);
59+
this.type = parseType(type);
6060
this.changeLogClass = changeLogClass;
6161
this.changeSetMethod = changeSetMethod;
6262
this.metadata = metadata;
6363
this.executionMillis = executionMillis;
6464
this.executionHostname = executionHostname;
6565
this.errorTrace = errorTrace;
66-
this.systemChange = systemChange;
66+
this.systemChange = normalizeSystemChange(systemChange);
6767
this.originalTimestamp = originalTimestamp;
6868
}
6969

@@ -112,7 +112,7 @@ public AuditEntry.ChangeType getType() {
112112
}
113113

114114
public void setType(String type) {
115-
this.type = MongockChangeType.valueOf(type);
115+
this.type = parseType(type);
116116
}
117117

118118
public String getChangeLogClass() {
@@ -168,7 +168,7 @@ public Boolean getSystemChange() {
168168
}
169169

170170
public void setSystemChange(Boolean systemChange) {
171-
this.systemChange = systemChange;
171+
this.systemChange = normalizeSystemChange(systemChange);
172172
}
173173

174174
public Date getOriginalTimestamp() {
@@ -183,6 +183,17 @@ public boolean shouldBeIgnored() {
183183
return state == MongockAuditEntry.MongockChangeState.IGNORED;
184184
}
185185

186+
private static MongockChangeType parseType(String type) {
187+
if (type == null || type.trim().isEmpty()) {
188+
return MongockChangeType.EXECUTION;
189+
}
190+
return MongockChangeType.valueOf(type);
191+
}
192+
193+
private static Boolean normalizeSystemChange(Boolean systemChange) {
194+
return systemChange != null ? systemChange : Boolean.FALSE;
195+
}
196+
186197

187198
public enum MongockChangeState {
188199
EXECUTED, FAILED, ROLLED_BACK, ROLLBACK_FAILED, IGNORED;

legacy/mongock-importer-mongodb/src/test/java/io/flamingock/importer/mongock/mongodb/MongoDBImporterTest.java

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@
2222
import com.mongodb.client.MongoDatabase;
2323
import io.flamingock.api.annotations.EnableFlamingock;
2424
import io.flamingock.api.annotations.Stage;
25+
import io.flamingock.common.test.mongock.MongockChangeEntry;
26+
import io.flamingock.common.test.mongock.MongockChangeState;
27+
import io.flamingock.common.test.mongock.MongockTestHelper;
2528
import io.flamingock.store.mongodb.sync.MongoDBSyncAuditStore;
2629
import io.flamingock.core.kit.TestKit;
2730
import io.flamingock.core.kit.audit.AuditTestHelper;
31+
import io.flamingock.internal.common.core.audit.AuditEntry;
2832
import io.flamingock.internal.common.core.response.data.ErrorInfo;
2933
import io.flamingock.internal.core.operation.StagedExecuteOperationException;
3034
import io.flamingock.internal.core.builder.runner.Runner;
@@ -47,12 +51,16 @@
4751

4852
import static io.flamingock.core.kit.audit.AuditEntryExpectation.APPLIED;
4953
import static io.flamingock.core.kit.audit.AuditEntryExpectation.STARTED;
54+
import static io.flamingock.core.kit.audit.AuditEntryExpectation.auditEntry;
5055
import static io.flamingock.internal.common.core.metadata.Constants.DEFAULT_MONGOCK_ORIGIN;
5156
import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_EMPTY_ORIGIN_ALLOWED_PROPERTY_KEY;
5257
import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_IGNORE_UNKNOWN_ENTRIES_PROPERTY_KEY;
5358
import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_ORIGIN_PROPERTY_KEY;
5459
import static io.flamingock.internal.common.core.metadata.Constants.MONGOCK_IMPORT_SKIP_PROPERTY_KEY;
5560
import static org.junit.jupiter.api.Assertions.assertEquals;
61+
import static org.junit.jupiter.api.Assertions.assertFalse;
62+
import static org.junit.jupiter.api.Assertions.assertNotNull;
63+
import static org.junit.jupiter.api.Assertions.assertNull;
5664
import static org.junit.jupiter.api.Assertions.assertThrows;
5765

5866
@Testcontainers
@@ -373,6 +381,52 @@ void GIVEN_allMongockChangeUnitsAlreadyExecutedAndCustomOriginProvidedByLiteralV
373381
Assertions.assertEquals("readonly", users.get(1).getList("roles", String.class).get(0));
374382
}
375383

384+
@Test
385+
@DisplayName("GIVEN Mongock v4 style audit entries without type, errorTrace and systemChange " +
386+
"WHEN migrating to Flamingock Community " +
387+
"THEN should import the history using v4 compatibility defaults")
388+
void GIVEN_mongockV4StyleAuditEntries_WHEN_migratingToFlamingockCommunity_THEN_shouldImportWithCompatibilityDefaults() {
389+
mongockTestHelper.writeAll(buildMongockV4ExecutedEntries());
390+
391+
MongoDBSyncTargetSystem mongodbTargetSystem = new MongoDBSyncTargetSystem("mongodb-target-system", mongoClient, DATABASE_NAME);
392+
393+
Runner flamingock = testKit.createBuilder()
394+
.addTargetSystem(mongodbTargetSystem)
395+
.build();
396+
397+
flamingock.run();
398+
399+
auditHelper.verifyAuditSequenceStrict(
400+
auditEntry().withChangeId("mongock-change-1")
401+
.withState(AuditEntry.Status.APPLIED)
402+
.withType(AuditEntry.ChangeType.MONGOCK_EXECUTION)
403+
.withSystemChange(false),
404+
auditEntry().withChangeId("mongock-change-2")
405+
.withState(AuditEntry.Status.APPLIED)
406+
.withType(AuditEntry.ChangeType.MONGOCK_EXECUTION)
407+
.withSystemChange(false),
408+
STARTED("migration-mongock-to-flamingock-community"),
409+
APPLIED("migration-mongock-to-flamingock-community"),
410+
STARTED("create-users-collection-with-index"),
411+
APPLIED("create-users-collection-with-index"),
412+
STARTED("seed-users"),
413+
APPLIED("seed-users")
414+
);
415+
416+
AuditEntry importedChange1 = getAuditEntryByChangeId("mongock-change-1");
417+
AuditEntry importedChange2 = getAuditEntryByChangeId("mongock-change-2");
418+
419+
assertNotNull(importedChange1);
420+
assertEquals(AuditEntry.ChangeType.MONGOCK_EXECUTION, importedChange1.getType());
421+
assertFalse(importedChange1.getSystemChange());
422+
assertNull(importedChange1.getErrorTrace());
423+
424+
assertNotNull(importedChange2);
425+
assertEquals(AuditEntry.ChangeType.MONGOCK_EXECUTION, importedChange2.getType());
426+
assertFalse(importedChange2.getSystemChange());
427+
assertNull(importedChange2.getErrorTrace());
428+
}
429+
376430
@Test
377431
@DisplayName("GIVEN Mongock audit history contains unknown entries " +
378432
"AND relaxed import flag is not provided " +
@@ -496,6 +550,54 @@ private static String firstFailedStageErrorMessage(StagedExecuteOperationExcepti
496550
.orElseThrow(() -> new AssertionError("Expected a failed stage with ErrorInfo"));
497551
}
498552

553+
private List<MongockChangeEntry> buildMongockV4ExecutedEntries() {
554+
try {
555+
List<MongockChangeEntry> entries = new ArrayList<>();
556+
entries.add(new MongockChangeEntry(
557+
"v4-execution-1",
558+
"mongock-change-1",
559+
"mongock",
560+
MongockTestHelper.DEFAULT_DATE_FORMAT.parse("2025-06-19T05:43:57.132Z"),
561+
MongockChangeState.EXECUTED,
562+
null,
563+
"io.mongock.examples.mongodb.standalone.mondogb.sync.migration.initializer.ClientInitializerChangeUnit",
564+
"apply",
565+
null,
566+
23L,
567+
MongockTestHelper.DEFAULT_HOSTNAME,
568+
null,
569+
null,
570+
null
571+
));
572+
entries.add(new MongockChangeEntry(
573+
"v4-execution-1",
574+
"mongock-change-2",
575+
"mongock",
576+
MongockTestHelper.DEFAULT_DATE_FORMAT.parse("2025-06-19T05:43:57.169Z"),
577+
MongockChangeState.EXECUTED,
578+
null,
579+
"io.mongock.examples.mongodb.standalone.mondogb.sync.migration.updater.ClientUpdaterChangeUnit",
580+
"apply",
581+
null,
582+
20L,
583+
MongockTestHelper.DEFAULT_HOSTNAME,
584+
null,
585+
null,
586+
null
587+
));
588+
return entries;
589+
} catch (Exception e) {
590+
throw new RuntimeException("Failed to build Mongock v4 test entries", e);
591+
}
592+
}
593+
594+
private AuditEntry getAuditEntryByChangeId(String changeId) {
595+
return auditHelper.getAuditEntriesSorted().stream()
596+
.filter(entry -> changeId.equals(entry.getChangeId()))
597+
.findFirst()
598+
.orElse(null);
599+
}
600+
499601

500602
@Test
501603
@DisplayName("GIVEN all Mongock changeUnits already executed " +

legacy/mongock-importer-mongodb/src/test/java/io/flamingock/importer/mongock/mongodb/MongoDBMongockTestHelper.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,22 @@ private Document convertToDocument(MongockChangeEntry entry) {
5555
document.put("changeId", entry.getChangeId());
5656
document.put("author", entry.getAuthor());
5757
document.put("timestamp", entry.getTimestamp());
58-
document.put("state", entry.getState() != null ? entry.getState().toString() : null);
59-
document.put("type", entry.getType() != null ? entry.getType().toString() : null);
60-
document.put("changeLogClass", entry.getChangeLogClass());
61-
document.put("changeSetMethod", entry.getChangeSetMethod());
62-
document.put("metadata", entry.getMetadata());
58+
putIfNotNull(document, "state", entry.getState() != null ? entry.getState().toString() : null);
59+
putIfNotNull(document, "type", entry.getType() != null ? entry.getType().toString() : null);
60+
putIfNotNull(document, "changeLogClass", entry.getChangeLogClass());
61+
putIfNotNull(document, "changeSetMethod", entry.getChangeSetMethod());
62+
putIfNotNull(document, "metadata", entry.getMetadata());
6363
document.put("executionMillis", entry.getExecutionMillis());
64-
document.put("executionHostname", entry.getExecutionHostname());
65-
document.put("errorTrace", entry.getErrorTrace());
66-
document.put("systemChange", entry.getSystemChange());
67-
document.put("originalTimestamp", entry.getOriginalTimestamp());
64+
putIfNotNull(document, "executionHostname", entry.getExecutionHostname());
65+
putIfNotNull(document, "errorTrace", entry.getErrorTrace());
66+
putIfNotNull(document, "systemChange", entry.getSystemChange());
67+
putIfNotNull(document, "originalTimestamp", entry.getOriginalTimestamp());
6868
return document;
6969
}
70+
71+
private void putIfNotNull(Document document, String key, Object value) {
72+
if (value != null) {
73+
document.put(key, value);
74+
}
75+
}
7076
}

0 commit comments

Comments
 (0)