diff --git a/application/src/main/java/run/halo/app/migration/impl/MigrationServiceImpl.java b/application/src/main/java/run/halo/app/migration/impl/MigrationServiceImpl.java index 1d99e64d8..a699a39cb 100644 --- a/application/src/main/java/run/halo/app/migration/impl/MigrationServiceImpl.java +++ b/application/src/main/java/run/halo/app/migration/impl/MigrationServiceImpl.java @@ -141,7 +141,14 @@ public class MigrationServiceImpl implements MigrationService, InitializingBean return Mono.usingWhen( createTempDir("halo-restore-", scheduler), tempDir -> unpackBackup(content, tempDir) - .then(Mono.defer(() -> restoreExtensions(tempDir))) + .then(Mono.defer(() -> + // This step skips index verification such as unique index. + // In order to avoid index conflicts after recovery or + // OptimisticLockingFailureException when updating the same record, + // so we need to truncate all extension stores before saving(create or update). + repository.deleteAll() + .then(restoreExtensions(tempDir))) + ) .then(Mono.defer(() -> restoreWorkdir(tempDir))), tempDir -> deleteRecursivelyAndSilently(tempDir, scheduler) ); @@ -241,13 +248,9 @@ public class MigrationServiceImpl implements MigrationService, InitializingBean sink.complete(); }) // reset version - .doOnNext(extensionStore -> extensionStore.setVersion(null)).buffer(100) - // We might encounter OptimisticLockingFailureException when saving extension - // store, - // So we have to delete all extension stores before saving. - .flatMap(extensionStores -> repository.deleteAll(extensionStores) - .thenMany(repository.saveAll(extensionStores)) - ) + .doOnNext(extensionStore -> extensionStore.setVersion(null)) + .buffer(100) + .flatMap(repository::saveAll) .doOnNext(extensionStore -> log.info("Restored extension store: {}", extensionStore.getName())) .then(), diff --git a/application/src/test/java/run/halo/app/migration/impl/MigrationServiceImplTest.java b/application/src/test/java/run/halo/app/migration/impl/MigrationServiceImplTest.java index e515e02c6..0d65e0134 100644 --- a/application/src/test/java/run/halo/app/migration/impl/MigrationServiceImplTest.java +++ b/application/src/test/java/run/halo/app/migration/impl/MigrationServiceImplTest.java @@ -120,7 +120,7 @@ class MigrationServiceImplTest { expectStore.setVersion(null); when(haloProperties.getWorkDir()).thenReturn(workdir); - when(repository.deleteAll(List.of(expectStore))).thenReturn(Mono.empty()); + when(repository.deleteAll()).thenReturn(Mono.empty()); when(repository.saveAll(List.of(expectStore))).thenReturn(Flux.empty()); var content = DataBufferUtils.read(backupFile, @@ -132,7 +132,7 @@ class MigrationServiceImplTest { verify(haloProperties).getWorkDir(); - verify(repository).deleteAll(List.of(expectStore)); + verify(repository).deleteAll(); verify(repository).saveAll(List.of(expectStore)); // make sure the workdir is recovered. diff --git a/ui/console-src/modules/system/backup/tabs/Restore.vue b/ui/console-src/modules/system/backup/tabs/Restore.vue index 6a0f940c7..a071a62a1 100644 --- a/ui/console-src/modules/system/backup/tabs/Restore.vue +++ b/ui/console-src/modules/system/backup/tabs/Restore.vue @@ -114,7 +114,9 @@ useQuery({