Fix: Download-Queue läuft nach fehlgeschlagenem Update weiter (kein Stillstand bis Neustart)

Beim Klick auf "Update" stoppt das Tool zuerst die laufende Session
(stop({parkForRestart:true}) → running=false, alle Items auf "Wartet") und
startet dann die Installation. Schlug die Installation fehl — und das ist auf
realistischen Wegen möglich (git.24-music.de-Aussetzer, Netz weg über alle
Versuche, oder ein Release mit fehlendem/falschem Digest → Integritätsprüfung
schlägt fehl) — kam KEIN App-Neustart (nur bei Erfolg wird app.quit geplant) und
auch kein In-Process-Resume. Folge: die komplette Queue stand still (alle Items
"Wartet"), bis ein Mensch "Start" klickte oder das Programm neu startete — auf
einem unbeaufsichtigten Server mit ~1 TB/h ein echter Stillstand.

Fix: Der Stop-Installieren-Resume-Ablauf liegt jetzt in
runInstallWithResume(): War vorher eine Session aktiv und schlägt die
Installation fehl, wird die Session wieder gestartet (manager.start(),
idempotent — die Items sind bereits "queued", der Scheduler nimmt sie normal
auf). Der Resume greift auf BEIDEN Fehlerpfaden: started:false UND geworfene
Ausnahme (try/catch). Bei Erfolg (started:true) wird NICHT resumed (die App
beendet sich gleich), und war keine Session aktiv, passiert nichts.

Test: started:false → resume; install wirft → resume + rethrow; started:true →
kein resume; nicht-laufend → kein stop/resume. Logik in eine reine, testbare
Funktion ausgelagert (kein schwergewichtiger AppController-Konstruktor nötig).
This commit is contained in:
Sucukdeluxe
2026-06-17 05:50:55 +02:00
parent 76b3f99476
commit dfd19260f6
3 changed files with 102 additions and 6 deletions
+34
View File
@@ -0,0 +1,34 @@
export interface InstallResumeManager {
isSessionRunning(): boolean;
stop(options: { parkForRestart: boolean }): void;
persistNowSync(): void;
start(): Promise<void> | void;
}
export async function runInstallWithResume<T extends { started: boolean }>(
manager: InstallResumeManager,
doInstall: () => Promise<T>
): Promise<T> {
const wasRunning = manager.isSessionRunning();
if (wasRunning) {
manager.stop({ parkForRestart: true });
}
manager.persistNowSync();
const resumeIfParked = async (): Promise<void> => {
if (wasRunning && !manager.isSessionRunning()) {
await manager.start();
}
};
try {
const result = await doInstall();
if (!result.started) {
await resumeIfParked();
}
return result;
} catch (error) {
await resumeIfParked();
throw error;
}
}