Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: unique index conflict issue after backup restoration preventing startup #6701

Merged
merged 4 commits into from
Oct 7, 2024
Merged
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 @@ -140,7 +140,14 @@ public Mono<Void> restore(Publisher<DataBuffer> content) {
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)
);
Expand Down Expand Up @@ -240,13 +247,9 @@ private Mono<Void> restoreExtensions(Path backupRoot) {
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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ void restoreTest() throws IOException, URISyntaxException {
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,
Expand All @@ -132,7 +132,7 @@ void restoreTest() throws IOException, URISyntaxException {


verify(haloProperties).getWorkDir();
verify(repository).deleteAll(List.of(expectStore));
verify(repository).deleteAll();
verify(repository).saveAll(List.of(expectStore));

// make sure the workdir is recovered.
Expand Down
4 changes: 3 additions & 1 deletion ui/console-src/modules/system/backup/tabs/Restore.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ useQuery({
<ul>
<li>{{ $t("core.backup.restore.tips.first") }}</li>
<li>
{{ $t("core.backup.restore.tips.second") }}
<strong>
{{ $t("core.backup.restore.tips.second") }}
</strong>
</li>
<li>
{{ $t("core.backup.restore.tips.third") }}
Expand Down
2 changes: 1 addition & 1 deletion ui/packages/components/src/components/dialog/Dialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const handleClose = () => {
<VModal
:visible="visible"
:width="450"
:layer-closable="true"
:layer-closable="false"
:data-unique-id="uniqueId"
@close="handleCancel()"
>
Expand Down
6 changes: 2 additions & 4 deletions ui/src/locales/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1402,14 +1402,12 @@ core:
first: >-
1. The restore process may last for a long time, please do not refresh
the page during this period.
second: >-
2. During the restore process, although the existing data will not be
cleaned up, if there is a conflict, the data will be overwritten.
second: 2. Before performing the restore, all existing data will be cleared. Please ensure that there is no data that needs to be retained.
third: >-
3. After the restore is completed, you need to restart Halo to load
the system resources normally.
complete: Restore completed, waiting for restart...
start: Start restore
start: I have read the above instructions, start restore
tabs:
local:
label: Upload
Expand Down
4 changes: 2 additions & 2 deletions ui/src/locales/zh-CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1302,10 +1302,10 @@ core:
restore:
tips:
first: 1. 恢复过程可能会持续较长时间,期间请勿刷新页面。
second: 2. 在恢复的过程中,虽然已有的数据不会被清理掉,但如果有冲突的数据将被覆盖
second: 2. 在执行恢复之前,会清空现有的所有数据,请确保当前没有需要保留的数据
third: 3. 恢复完成之后需要重启 Halo 才能够正常加载系统资源。
complete: 恢复完成,等待重启...
start: 开始恢复
start: 我已阅读上方提示,开始恢复
tabs:
local:
label: 上传
Expand Down
4 changes: 2 additions & 2 deletions ui/src/locales/zh-TW.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1281,10 +1281,10 @@ core:
restore:
tips:
first: 1. 還原過程可能需要較長時間,期間請勿重新整理頁面。
second: 2. 在還原過程中,雖然已有的資料不會被清除,但若有衝突的資料將被覆蓋
second: 2. 在執行恢復之前,會清空現有的所有數據,請確保當前沒有需要保留的數據
third: 3. 還原完成後需要重新啟動 Halo 才能正常載入系統資源。
complete: 還原完成,等待重啟...
start: 開始還原
start: 我已閱讀上方提示,開始恢復
tabs:
local:
label: 上傳
Expand Down
Loading