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).
35 lines
833 B
TypeScript
35 lines
833 B
TypeScript
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;
|
|
}
|
|
}
|