M2 sauber gelöst: Auto-Relaunch nach Backup-Import
Problem: nach importBackup hielt der Manager weiter die STALE In-Memory-Session (Import schrieb nur auf Disk). blockAllPersistence wurde gesetzt um Überschreiben zu verhindern, aber nie zurückgesetzt → ignorierte der User die manuelle "Bitte neustarten"-Aufforderung und arbeitete weiter, ging bei hartem Crash alles verloren (stille Persistenz-Blockade). In-Memory-Reload verworfen: aborted activeTasks settlen ASYNC und greifen in ihren finally-Blöcken auf this.session.items[id] zu — ein Session-Swap würde dagegen racen. Sicherer Reload bräuchte async-Refactor (alle Tasks awaiten). Lösung: Auto-Relaunch. Nach restored===true startet main.ts die App automatisch neu (1.5s Delay für Toast). Der frische Prozess lädt die restored Session sauber über den bewährten Startup-Pfad — null Stale-State-Risiko. Main-getrieben (nicht Renderer), damit ein Renderer-Fehler den Restart nicht verhindern kann. skipShutdownPersist/blockAllPersistence schützen weiterhin das kurze Fenster + den Quit (prepareForShutdown:5680 überspringt Persistenz sauber, fasst die stale Session nicht an). Nach Relaunch: frischer Prozess, Flags zurückgesetzt — Footgun weg. 621 Tests grün, tsc-Fehlerzahl unverändert (9 pre-existing). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
6dc32303a0
commit
682bd1d759
@@ -673,15 +673,23 @@ export class AppController {
|
||||
|
||||
resetHistoryForRetention(this.storagePaths, this.settings.historyRetentionMode);
|
||||
|
||||
// Prevent prepareForShutdown from overwriting the restored data
|
||||
// Block runtime + shutdown persistence so the STALE in-memory session (the
|
||||
// manager still holds the PRE-import session — importBackup only wrote to disk)
|
||||
// cannot overwrite the restored data in the brief window before the auto-relaunch.
|
||||
// The relaunch (triggered in main.ts when restored===true) starts a fresh process
|
||||
// that loads the restored session cleanly via the normal startup path, so these
|
||||
// flags never linger in a live session.
|
||||
// M2-Fix: vorher blieb blockAllPersistence dauerhaft true wenn der User die
|
||||
// manuelle "Bitte neustarten"-Aufforderung ignorierte → stille Persistenz-Blockade,
|
||||
// alle weiteren Änderungen gingen bei hartem Crash verloren. Jetzt: Auto-Relaunch.
|
||||
this.manager.skipShutdownPersist = true;
|
||||
this.manager.blockAllPersistence = true;
|
||||
logger.info("Backup wiederhergestellt (verschlüsseltes Format)");
|
||||
logger.info("Backup wiederhergestellt — App startet automatisch neu");
|
||||
this.audit("WARN", "Backup importiert", {
|
||||
historyEntries: Array.isArray(parsed.history) ? parsed.history.length : 0,
|
||||
accountSummary: buildAccountSummary(this.settings)
|
||||
});
|
||||
return { restored: true, message: "Backup wiederhergestellt. Bitte App neustarten." };
|
||||
return { restored: true, message: "Backup wiederhergestellt – App startet automatisch neu…" };
|
||||
}
|
||||
|
||||
public getSessionLogPath(): string | null {
|
||||
|
||||
+14
-1
@@ -664,7 +664,20 @@ function registerIpcHandlers(): void {
|
||||
return { restored: false, message: `Backup-Datei zu groß (max 50 MB, Datei hat ${(stat.size / 1024 / 1024).toFixed(1)} MB)` };
|
||||
}
|
||||
const data = await fs.promises.readFile(filePath);
|
||||
return controller.importBackup(data);
|
||||
const importResult = controller.importBackup(data);
|
||||
if (importResult.restored) {
|
||||
// M2: Nach erfolgreichem Import die App automatisch neu starten. Der frische
|
||||
// Prozess lädt die wiederhergestellte Session sauber vom Disk (kein Stale-
|
||||
// In-Memory-State, kein dauerhaft blockierter Persist in einer lebenden Session).
|
||||
// Vom Main getrieben (nicht Renderer), damit ein Renderer-Fehler den Restart
|
||||
// nicht verhindern kann. Kurze Verzögerung, damit das Ergebnis den Renderer
|
||||
// erreicht (Toast "App startet automatisch neu…").
|
||||
setTimeout(() => {
|
||||
app.relaunch();
|
||||
app.quit();
|
||||
}, 1500);
|
||||
}
|
||||
return importResult;
|
||||
});
|
||||
|
||||
controller.onState = (snapshot) => {
|
||||
|
||||
Reference in New Issue
Block a user