Fix: Komplett leere Liste nach unsauberem Neustart (Datenverlust bei Stromausfall/Crash waehrend Download)
Ursache: Session-Writes (writeFile + atomic rename) liefen ohne fsync. Waehrend eines Downloads feuert persistSoon alle 700ms-3s, die Session-Datei bleibt damit dauerhaft dirty im OS-Cache. Bei hartem Stromausfall auf NTFS ist die rename-Metadatentransaktion journaled (durable), aber die Datenbloecke der temp-Datei sind nicht geflusht -> primary zeigt nach Reboot auf Null/Garbage. Die .bak-Kopie stammt per copyFileSync aus einer ebenfalls ungeflushten primary -> ebenfalls korrupt. loadSession faellt durch primary -> bak -> temp auf emptySession() durch, und der naechste persistSoon speichert diese leere Session ueber die Platte -> dauerhaft leer. Tritt nur bei UNSAUBEREM Neustart auf (sauberes Beenden flusht ohnehin). Fix in drei Schichten: - Durable atomic write: temp wird vor dem rename gefsynct. Reihenfolge zwingend write -> fsync -> close -> rename (NTFS kann eine Datei mit offenem Handle nicht renamen). Sync-Pfad via openSync/writeSync/fsyncSync/closeSync, Async-Pfad via FileHandle.sync() (laeuft auf dem libuv-Threadpool, blockiert den Hot-Path nicht). Kein Throttle: ein throttle-skip wuerde eine ungeflushte temp ueber die durable primary renamen und das Korruptionsfenster wieder oeffnen. - Read-Retry: readSessionFile wiederholt bei transienten Sperren (EBUSY/EPERM/EAGAIN, z.B. Virenscanner/Disk-not-ready beim Boot) 5x mit Backoff. EACCES und JSON-Parse-Fehler werden nicht wiederholt. - Empty-Clobber-Guard: loadSessionWithStatus meldet, ob alle Tiers unlesbar waren (Status empty-unreadable). In dem Fall blockiert der DownloadManager das Speichern einer leeren Session ueber vorhandene Daten, bis wieder echte Daten vorliegen; die erste nicht-leere Speicherung hebt den Schutz auf. Tests: tests/session-restart-loss.test.ts um Status-Klassifizierung, fsync-Nachweis, async-Roundtrip (close-before-rename), EBUSY-Retry und Guard-Clear-Pfad erweitert. Suite 929 gruen, tsc unveraendert bei 6 Baseline-Fehlern.
This commit is contained in:
Binary file not shown.
Reference in New Issue
Block a user