Prevent queue loss during app updates

- Increase quit timeout from 900ms to 5000ms to ensure pending saves complete
- Add persistNowSync() called before update install to flush queue to disk
- Remove blockAllPersistence from shutdown save condition — shutdown must
  always persist to prevent data loss across restarts
- Add temp file recovery as last resort when both primary and backup
  session files are corrupted

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe
2026-03-26 19:34:48 +01:00
co-authored by Claude Opus 4.6
parent ffb48a8883
commit 5aeab9ecad
4 changed files with 606 additions and 570 deletions
+18 -3
View File
@@ -4696,9 +4696,12 @@ export class DownloadManager extends EventEmitter {
this.pacedStartReservationByItem.clear();
this.nonResumableActive = 0;
this.session.summaryText = "";
// Persist synchronously on shutdown to guarantee data is written before process exits
// Skip if a backup was just imported — the restored session on disk must not be overwritten
if (!this.skipShutdownPersist && !this.blockAllPersistence) {
// Persist synchronously on shutdown to guarantee data is written before process exits.
// Only skip if a backup was just imported (skipShutdownPersist) — the restored session
// on disk must not be overwritten. blockAllPersistence is intentionally NOT checked
// here: it guards async/periodic saves during runtime, but shutdown must always persist
// to prevent queue loss across restarts/updates.
if (!this.skipShutdownPersist) {
const pkgCount = Object.keys(this.session.packages).length;
const itemCount = Object.keys(this.session.items).length;
logger.info(`Shutdown-Save: ${pkgCount} Pakete, ${itemCount} Items`);
@@ -5030,6 +5033,18 @@ export class DownloadManager extends EventEmitter {
}
}
/** Synchronous persist guarantees state is on disk before returning.
* Used before update installs to prevent queue loss. */
public persistNowSync(): void {
this.clearPersistTimer();
const pkgCount = Object.keys(this.session.packages).length;
const itemCount = Object.keys(this.session.items).length;
logger.info(`Pre-Update Sync-Save: ${pkgCount} Pakete, ${itemCount} Items`);
this.foldRuntimeIntoSettings(nowMs());
saveSession(this.storagePaths, this.session);
saveSettings(this.storagePaths, this.settings);
}
private emitState(force = false): void {
const now = nowMs();
const MIN_FORCE_GAP_MS = 120;