Skip to content

Commit da7b956

Browse files
Fix: backfill historical gaps in SERVER_CHANGE_LOG during migrate (#27703)
processNativeMigrations used sameOrHigherMajorMinor to gate unexecuted migrations by the current max's major.minor. That gate silently drops any version recorded on disk but missing from the ledger whose major.minor is lower than the current max — for example a historical gap at 1.5.15 when the dump was last migrated through 1.9.x, or a backported 1.11.11 landing after 1.12.1 was already cut. The containment check against SERVER_CHANGE_LOG is sufficient on its own: any version already executed is skipped, any version not executed is planned. Maintaining the reprocessing-on-maxVer path preserves the continuous-release behavior introduced in #26571 (new SQL appended to the current version's schemaChanges.sql is picked up via checksum filter in SERVER_MIGRATION_SQL_LOGS). This also brings processNativeMigrations in line with processExtensionMigrations, which already uses the same containment-only filter. See also #26592 which applied the equivalent simplification on the 1.12.x release line. Tests: - Updated three tests that encoded the old exclusion behavior to assert backports and historical gaps now get planned. - Added a historical-gap scenario (1.5.15 below executed max 1.10.5). - Removed sameOrHigherMajorMinorComparisons (method is gone). Co-authored-by: Mohit Yadav <105265192+mohityadav766@users.noreply.github.com> (cherry picked from commit 8fe3014)
1 parent beacaa4 commit da7b956

2 files changed

Lines changed: 73 additions & 30 deletions

File tree

openmetadata-service/src/main/java/org/openmetadata/service/migration/api/MigrationWorkflow.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,6 @@ private static int[] parseVersion(String version) {
252252
return numbers;
253253
}
254254

255-
static boolean sameOrHigherMajorMinor(String version, String maxVersion) {
256-
int[] v = parseVersion(version);
257-
int[] max = parseVersion(maxVersion);
258-
if (v[0] != max[0]) return v[0] > max[0];
259-
return v[1] >= max[1];
260-
}
261-
262255
// Package-private for testing
263256
List<MigrationFile> resolveApplyMigrations(List<MigrationFile> availableMigrations) {
264257
LOG.debug("Filtering Server Migrations");
@@ -310,8 +303,7 @@ private List<MigrationFile> processNativeMigrations(
310303
for (MigrationFile migration : nativeMigrations) {
311304
if (migration.version.equals(maxVer)) {
312305
result.add(migration.copyWithReprocessing(true));
313-
} else if (!executedMigrations.contains(migration.version)
314-
&& sameOrHigherMajorMinor(migration.version, maxVer)) {
306+
} else if (!executedMigrations.contains(migration.version)) {
315307
result.add(migration.copyWithReprocessing(false));
316308
}
317309
}

openmetadata-service/src/test/java/org/openmetadata/service/migration/api/MigrationWorkflowTest.java

Lines changed: 72 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ void runMigrationWorkflowsExecutesDataMigrationForReprocessing() throws Exceptio
381381
}
382382

383383
@Test
384-
void getMigrationsToApplyOlderMinorBackfillsExcludedWhenOnHigherMinor() throws Exception {
384+
void getMigrationsToApplyBackportedLowerMinorVersionsAreIncluded() throws Exception {
385385
List<String> executedMigrations = List.of("1.11.10", "1.12.0", "1.12.1");
386386
List<MigrationFile> availableMigrations =
387387
List.of(
@@ -400,9 +400,31 @@ void getMigrationsToApplyOlderMinorBackfillsExcludedWhenOnHigherMinor() throws E
400400
workflow.getMigrationsToApply(executedMigrations, availableMigrations);
401401

402402
List<String> versions = result.stream().map(m -> m.version).toList();
403-
assertEquals(List.of("1.12.1", "1.12.2"), versions);
404-
assertTrue(result.get(0).isReprocessing());
405-
assertFalse(result.get(1).isReprocessing());
403+
assertEquals(List.of("1.11.11", "1.11.12", "1.12.1", "1.12.2"), versions);
404+
assertFalse(
405+
result.stream()
406+
.filter(m -> m.version.equals("1.11.11"))
407+
.findFirst()
408+
.orElseThrow()
409+
.isReprocessing());
410+
assertFalse(
411+
result.stream()
412+
.filter(m -> m.version.equals("1.11.12"))
413+
.findFirst()
414+
.orElseThrow()
415+
.isReprocessing());
416+
assertTrue(
417+
result.stream()
418+
.filter(m -> m.version.equals("1.12.1"))
419+
.findFirst()
420+
.orElseThrow()
421+
.isReprocessing());
422+
assertFalse(
423+
result.stream()
424+
.filter(m -> m.version.equals("1.12.2"))
425+
.findFirst()
426+
.orElseThrow()
427+
.isReprocessing());
406428
}
407429

408430
@Test
@@ -429,7 +451,7 @@ void getMigrationsToApplyCollateVersionsAreIncluded() throws Exception {
429451
List<String> extensionVersions =
430452
result.stream().filter(m -> m.isExtension).map(m -> m.version).toList();
431453

432-
assertEquals(List.of("1.12.1", "1.12.2"), nativeVersions);
454+
assertEquals(List.of("1.11.11", "1.12.1", "1.12.2"), nativeVersions);
433455
assertEquals(List.of("1.12.1-collate"), extensionVersions);
434456
assertTrue(result.stream().anyMatch(m -> m.version.equals("1.12.1") && m.isReprocessing()));
435457
assertTrue(
@@ -577,7 +599,7 @@ void getMigrationsToApplyAllMigrationsAlreadyExecuted() throws Exception {
577599
}
578600

579601
@Test
580-
void getMigrationsToApplyMultipleBackportedMinorVersionsExcluded() throws Exception {
602+
void getMigrationsToApplyMultipleBackportedMinorVersionsAreIncluded() throws Exception {
581603
List<String> executedMigrations = List.of("1.10.5", "1.11.0", "1.12.0", "1.12.1");
582604
List<MigrationFile> availableMigrations =
583605
List.of(
@@ -598,8 +620,50 @@ void getMigrationsToApplyMultipleBackportedMinorVersionsExcluded() throws Except
598620
workflow.getMigrationsToApply(executedMigrations, availableMigrations);
599621

600622
List<String> versions = result.stream().map(m -> m.version).toList();
601-
assertEquals(List.of("1.12.1", "1.12.2"), versions);
602-
assertTrue(result.get(0).isReprocessing());
623+
assertEquals(List.of("1.10.6", "1.11.1", "1.11.1-collate", "1.12.1", "1.12.2"), versions);
624+
assertTrue(
625+
result.stream()
626+
.filter(m -> m.version.equals("1.12.1"))
627+
.findFirst()
628+
.orElseThrow()
629+
.isReprocessing());
630+
}
631+
632+
@Test
633+
void getMigrationsToApplyHistoricalGapBelowMaxIsBackfilled() throws Exception {
634+
List<String> executedMigrations =
635+
List.of("1.5.0", "1.5.11", "1.9.0", "1.9.1", "1.10.0", "1.10.5");
636+
List<MigrationFile> availableMigrations =
637+
List.of(
638+
createMigrationFile("1.5.0", false),
639+
createMigrationFile("1.5.11", false),
640+
createMigrationFile("1.5.15", false),
641+
createMigrationFile("1.9.0", false),
642+
createMigrationFile("1.9.1", false),
643+
createMigrationFile("1.10.0", false),
644+
createMigrationFile("1.10.5", false));
645+
646+
MigrationWorkflow workflow =
647+
new MigrationWorkflow(
648+
jdbi, tempDir.toString(), ConnectionType.MYSQL, null, null, config, false);
649+
650+
List<MigrationFile> result =
651+
workflow.getMigrationsToApply(executedMigrations, availableMigrations);
652+
653+
List<String> versions = result.stream().map(m -> m.version).toList();
654+
assertEquals(List.of("1.5.15", "1.10.5"), versions);
655+
assertFalse(
656+
result.stream()
657+
.filter(m -> m.version.equals("1.5.15"))
658+
.findFirst()
659+
.orElseThrow()
660+
.isReprocessing());
661+
assertTrue(
662+
result.stream()
663+
.filter(m -> m.version.equals("1.10.5"))
664+
.findFirst()
665+
.orElseThrow()
666+
.isReprocessing());
603667
}
604668

605669
@Test
@@ -667,19 +731,6 @@ void resolveApplyMigrationsAllExecutedNoDuplicates() throws Exception {
667731
assertTrue(result.get(0).isReprocessing());
668732
}
669733

670-
@Test
671-
void sameOrHigherMajorMinorComparisons() {
672-
assertTrue(MigrationWorkflow.sameOrHigherMajorMinor("1.12.0", "1.12.1"));
673-
assertTrue(MigrationWorkflow.sameOrHigherMajorMinor("1.12.5", "1.12.1"));
674-
assertTrue(MigrationWorkflow.sameOrHigherMajorMinor("1.13.0", "1.12.1"));
675-
assertTrue(MigrationWorkflow.sameOrHigherMajorMinor("2.0.0", "1.12.1"));
676-
assertFalse(MigrationWorkflow.sameOrHigherMajorMinor("1.11.15", "1.12.1"));
677-
assertFalse(MigrationWorkflow.sameOrHigherMajorMinor("1.10.6", "1.12.1"));
678-
assertFalse(MigrationWorkflow.sameOrHigherMajorMinor("0.13.0", "1.12.1"));
679-
assertTrue(MigrationWorkflow.sameOrHigherMajorMinor("1.12.1-collate", "1.12.1"));
680-
assertFalse(MigrationWorkflow.sameOrHigherMajorMinor("1.11.1-collate", "1.12.1"));
681-
}
682-
683734
private void mockContext(
684735
MigrationWorkflowContext contextMock, org.mockito.MockedConstruction.Context context) {
685736
HashMap<String, MigrationContext> contexts = new HashMap<>();

0 commit comments

Comments
 (0)