Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,22 @@
import io.flamingock.internal.common.core.audit.AuditEntry;
import io.flamingock.internal.common.core.audit.AuditHistoryReader;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class MongockImporterMongoDB implements AuditHistoryReader {

private static final Logger logger = LoggerFactory.getLogger("MongockImporter");

private final MongoCollection<Document> sourceCollection;

public MongockImporterMongoDB(MongoDatabase mongoDatabase, String collectionName) {
Expand All @@ -44,6 +49,7 @@ public List<AuditEntry> getAuditHistory() {
.into(new ArrayList<>())
.stream()
.map(MongockImporterMongoDB::toAuditEntry)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

Expand All @@ -55,6 +61,8 @@ private static AuditEntry toAuditEntry(Document document) {
.toLocalDateTime();

if (changeEntry.shouldBeIgnored()) {
logger.info("Skipping Mongock audit entry with changeId[{}]: state=IGNORED (Mongock never executed this change; nothing to import).",
changeEntry.getChangeId());
return null;
}
return new AuditEntry(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,65 @@ void GIVEN_unknownAuditEntriesAndRelaxedMode_WHEN_migratingToFlamingockCommunity
);
}

@Test
@DisplayName("GIVEN Mongock audit history contains an IGNORED entry " +
"WHEN migrating to Flamingock Community " +
"THEN should skip the IGNORED entry without crashing " +
"AND import the rest of the history normally")
void GIVEN_ignoredAuditEntry_WHEN_migratingToFlamingockCommunity_THEN_shouldSkipIgnoredAndImportRest() throws java.text.ParseException {
// Regression test for IGNORED-state null leak in MongockImporterMongoDB.toAuditEntry().
// Before the fix, the importer returned null for IGNORED entries and the caller
// (MongockImportChange.importHistory) crashed with:
// NullPointerException: Cannot invoke "AuditEntry.getSystemChange()"
// because "auditEntryFromOrigin" is null
// The fix filters nulls at both layers and logs the skipped entry.

mongockTestHelper.setupBasicScenario();
mongockTestHelper.write(new MongockChangeEntry(
"ignored-execution-1",
"ignored-change",
"mongock",
MongockTestHelper.DEFAULT_DATE_FORMAT.parse("2025-06-19T05:43:57.200Z"),
MongockChangeState.IGNORED,
io.flamingock.common.test.mongock.MongockChangeType.EXECUTION,
"io.example.IgnoredChangeUnit",
"apply",
null,
0L,
MongockTestHelper.DEFAULT_HOSTNAME,
null,
false,
null
));

MongoDBSyncTargetSystem mongodbTargetSystem = new MongoDBSyncTargetSystem("mongodb-target-system", mongoClient, DATABASE_NAME);

Runner flamingock = testKit.createBuilder()
.addTargetSystem(mongodbTargetSystem)
.build();

flamingock.run();

// IGNORED entry must NOT appear in the Flamingock audit store.
assertNull(getAuditEntryByChangeId("ignored-change"),
"IGNORED Mongock entry must not be imported into the Flamingock audit store");

// Remaining basic-scenario entries imported as normal, plus native changes executed.
auditHelper.verifyAuditSequenceStrict(
APPLIED("system-change-00001_before"),
APPLIED("system-change-00001"),
APPLIED("mongock-change-1_before"),
APPLIED("mongock-change-1"),
APPLIED("mongock-change-2"),
STARTED("migration-mongock-to-flamingock-community"),
APPLIED("migration-mongock-to-flamingock-community"),
STARTED("create-users-collection-with-index"),
APPLIED("create-users-collection-with-index"),
STARTED("seed-users"),
APPLIED("seed-users")
);
}

@Test
@DisplayName("GIVEN relaxed import flag with invalid value " +
"WHEN migrating to Flamingock Community " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@

import javax.inject.Named;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

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;
Expand Down Expand Up @@ -61,7 +63,10 @@ public void importHistory(@Named("change.targetSystem.id") String targetSystemId
logger.info("Starting audit log migration from Mongock to Flamingock community audit store");
AuditHistoryReader legacyHistoryReader = getAuditHistoryReader(targetSystemId, targetSystemManager);
PipelineHelper pipelineHelper = new PipelineHelper(pipelineDescriptor);
List<AuditEntry> legacyHistory = legacyHistoryReader.getAuditHistory();
List<AuditEntry> legacyHistory = legacyHistoryReader.getAuditHistory()
.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
boolean ignoreUnknownEntries = resolveIgnoreUnknownEntries(ignoreUnknownEntriesPropertyValue);
validate(legacyHistory, targetSystemId, emptyOriginAllowedPropertyValue);
legacyHistory.forEach(auditEntryFromOrigin -> {
Expand Down
Loading