Skip to content

Commit 2878425

Browse files
committed
fix(review-feedback-1256): address latest review comments
1 parent e8c59b0 commit 2878425

2 files changed

Lines changed: 38 additions & 22 deletions

File tree

apps/dsa-desktop/main.js

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -476,21 +476,26 @@ function backupPackagedRuntimeState() {
476476
}
477477

478478
function restorePackagedRuntimeStateFromBackup() {
479+
const result = {
480+
backupRoot: null,
481+
restored: [],
482+
failed: [],
483+
};
484+
479485
if (!isWindowsNsisInstalledApp()) {
480-
return;
486+
return result;
481487
}
482488

483489
const manifest = readUpdateBackupManifest();
484490
if (!manifest) {
485-
return;
491+
return result;
486492
}
487493

488494
const appDir = resolveAppDir();
489495
const backupRoot = resolveUpdateBackupRoot();
496+
result.backupRoot = backupRoot;
490497
const runtimeEntries = resolveRuntimeFileEntries(appDir);
491498
const relativeFiles = normalizeBackupFileList(manifest);
492-
const restored = [];
493-
const failed = [];
494499

495500
try {
496501
relativeFiles.forEach((relativePath) => {
@@ -503,22 +508,26 @@ function restorePackagedRuntimeStateFromBackup() {
503508
}
504509
ensureDirectory(path.dirname(target));
505510
fs.copyFileSync(source, target);
506-
restored.push(relativePath);
511+
result.restored.push(relativePath);
507512
} catch (error) {
508513
const message = error instanceof Error ? error.message : String(error);
509-
failed.push(`${relativePath} (${message})`);
514+
result.failed.push(`${relativePath} (${message})`);
510515
}
511516
});
512517
} finally {
513-
cleanupUpdateBackupRoot();
518+
if (!result.failed.length) {
519+
cleanupUpdateBackupRoot();
520+
}
514521
}
515522

516-
if (restored.length) {
517-
console.log(`[update] restored runtime files from backup: ${restored.join(', ')}`);
523+
if (result.restored.length) {
524+
console.log(`[update] restored runtime files from backup: ${result.restored.join(', ')}`);
518525
}
519-
if (failed.length) {
520-
logLine(`[update] skipped runtime restore files after copy failure: ${failed.join(', ')}`);
526+
if (result.failed.length) {
527+
logLine(`[update] skipped runtime restore files after copy failure: ${result.failed.join(', ')}`);
521528
}
529+
530+
return result;
522531
}
523532

524533
function resolveBackendPath() {
@@ -1331,14 +1340,17 @@ ipcMain.handle('desktop:open-release-page', async (_event, releaseUrl) => {
13311340
});
13321341

13331342
async function createWindow() {
1334-
if (isWindowsNsisInstalledApp()) {
1335-
restorePackagedRuntimeStateFromBackup();
1336-
}
1343+
const restoreResult = isWindowsNsisInstalledApp() ? restorePackagedRuntimeStateFromBackup() : null;
13371344
initLogging();
1345+
const restoreFailed = Boolean(restoreResult && restoreResult.failed.length);
1346+
const restoreErrorMessage = restoreFailed
1347+
? `上次更新安装后恢复运行时文件失败,已保留备份目录 ${restoreResult.backupRoot},请确认后手动恢复并重启应用。失败明细:${restoreResult.failed.join(';')}`
1348+
: '';
13381349
setDesktopUpdateState({
1339-
status: UPDATE_STATUS.IDLE,
1350+
status: restoreFailed ? UPDATE_STATUS.ERROR : UPDATE_STATUS.IDLE,
13401351
currentVersion: resolveDesktopVersion(),
1341-
message: '',
1352+
updateMode: restoreFailed ? UPDATE_MODE.MANUAL : UPDATE_MODE.AUTO,
1353+
message: restoreErrorMessage,
13421354
});
13431355
const startupStartedAt = Date.now();
13441356
const logStartup = (message) => {
@@ -1496,7 +1508,9 @@ async function createWindow() {
14961508
await mainWindow.loadURL(`http://127.0.0.1:${port}/`);
14971509
logStartup(`Main page loadURL resolved in ${Date.now() - mainPageStartedAt}ms`);
14981510
logStartup(`Main UI loaded in ${Date.now() - startupStartedAt}ms`);
1499-
void performDesktopUpdateCheck({ notify: true });
1511+
if (!restoreFailed) {
1512+
void performDesktopUpdateCheck({ notify: true });
1513+
}
15001514
} catch (error) {
15011515
logStartup(`Startup failed while waiting for health: ${String(error)}`);
15021516
const errorUrl = `file://${loadingPath}?error=${encodeURIComponent(String(error))}`;

apps/dsa-desktop/tests/main.test.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ test('desktop update backup list includes WAL and SHM artifacts', (t) => {
231231
assert.ok(files.includes(path.join('logs', 'desktop.log')));
232232
});
233233

234-
test('restorePackagedRuntimeStateFromBackup skips failed copies and clears backup', (t) => {
234+
test('restorePackagedRuntimeStateFromBackup keeps backup when copy fails', (t) => {
235235
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'dsa-desktop-restore-'));
236236
const appDir = path.join(tempRoot, 'app');
237237
const userDataDir = path.join(tempRoot, 'userData');
@@ -275,11 +275,13 @@ test('restorePackagedRuntimeStateFromBackup skips failed copies and clears backu
275275
fs.rmSync(tempRoot, { recursive: true, force: true });
276276
});
277277

278-
assert.doesNotThrow(() => {
279-
mainModule.restorePackagedRuntimeStateFromBackup();
280-
});
278+
const restoreResult = mainModule.restorePackagedRuntimeStateFromBackup();
281279
assert.equal(failedCopyAttempted, true);
282-
assert.equal(fs.existsSync(backupRoot), false);
280+
assert.equal(Array.isArray(restoreResult.failed), true);
281+
assert.equal(restoreResult.failed.length > 0, true);
282+
assert.equal(fs.existsSync(backupRoot), true);
283+
assert.equal(fs.existsSync(path.join(backupRoot, 'runtime-state.json')), true);
284+
assert.equal(restoreResult.failed[0].includes('target locked'), true);
283285
});
284286

285287
test('stopBackend waits for backend process exit', async (t) => {

0 commit comments

Comments
 (0)