real-debrid-downloader/tasks/todo.md
Sucukdeluxe 7d52d5a495 Deferred-Post-Processing Lifecycle härten (H1/H2/M1) + 0-Byte-Fix (H3) + Dead Code (N1)
Aus der Bug-Analyse (3 Subagents): die Deferred-Post-Processing-Pipeline war
nur halb ins Abbruch-/Lifecycle-Management integriert — gleiche Ecke wie der
v1.7.156-Datenverlust.

H1: abortPostProcessing (globaler Stop/Shutdown/clearAll/external) bricht jetzt
    auch packageDeferredPostProcessAbortControllers + die neue Hybrid-Map ab.
    Vorher rasten MKV-Move/Cleanup/Rename gegen den synchronen Shutdown-Save.

H2: Hybrid-Post-Extract (Rename+MKV-Collect) lief als komplett ungetracktes
    detached Promise. Jetzt in packageHybridPostProcessControllers (Set/Package)
    registriert — SYNCHRON vor dem Promise, mit shouldAbort an beide Aufrufe.
    Bewusst SEPARAT von der Deferred-Map, sonst würde runDeferredPostExtraction's
    replace-Logik die laufende Hybrid-Arbeit selbst killen (Advisor-Fund).
    Cancel/Reset/Stop stoppt jetzt laufende Hybrid-Verschiebungen.

M1: hasAnyDeferredPostProcessPending() — Scheduler-Abschluss + finishRun-Clear
    gaten darauf. Run endet/Summary feuert nicht mehr während im Hintergrund
    noch Dateien verschoben werden; Run-State wird nicht mehr mittendrin geleert.

H3: validateDownloadedFileCompletion akzeptierte 0-Byte bei source=stream-end
    (kein Content-Length, keine Provider-Größe) als "fertig". Jetzt ok:false
    -> bestehender download_underflow-Retry-Pfad. Verhindert leere Datei = komplett.

N1: toter (unerreichbarer) Disk-Fallback-Block in findReadyArchiveSets +
    verwaiste pendingItemStatus-Map entfernt (verhaltensneutral).

Bewusst übersprungen: M2 (blockAllPersistence — vorgeschlagener Reset wäre
unsicher, In-Memory-Session ist nach Import stale) und M3 (cancelPendingAsyncSaves
— Generation-Guard schützt Korrektheit bereits). Siehe tasks/todo.md.

8 neue Tests (tests/download-completion.test.ts) inkl. H3-Regression. 621 Tests grün.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 16:39:34 +02:00

71 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Real-Debrid-Downloader — Analyse & Verbesserungen (2026-05-23)
Tiefe Analyse via 3 parallele Subagents (Bugs / Features / UI) + 4 Design-Mockups.
---
## A. BUGS / ROBUSTHEIT (verifiziert gegen Quellcode)
Roter Faden: Die **Deferred-Post-Processing-Pipeline** (eingeführt um den Extract-Slot schnell freizugeben) ist nur halb ins Abbruch-/Lifecycle-Management integriert. Genau der Bereich des v1.7.156-Fixes.
### HOCH
- [ ] **H1 — Globaler Stop/Shutdown bricht Deferred-Post-Processing nicht ab.** `abortPostProcessing` (download-manager.ts:7053) iteriert nur über `packagePostProcessAbortControllers`, nie über `packageDeferredPostProcessAbortControllers`. Bei Stop/Shutdown/clearAll laufen MKV-Move/Archiv-Cleanup/Rename weiter, während synchron persistiert wird → FS-Zustand ≠ Session-State (halb verschobene Datei, halb gelöschtes Archiv).
- [ ] **H2 — Hybrid-Post-Extract feuert MKV-Collection/Rename als losgelöstes Promise** (download-manager.ts:11334). In keiner Tracking-Map, kein `shouldAbort`. Cancel/Reset während Hybrid-Collect → Dateien werden trotzdem verschoben/gelöscht.
- [ ] **H3 — 0-Byte-Datei wird als vollständig akzeptiert** wenn keine Größeninfo (download-completion.ts:129, source "stream-end"). Hoster antwortet HTTP 200 ohne Content-Length + schließt sofort → Item "Fertig" mit leerer Datei, kein Auto-Redownload.
### MITTEL
- [ ] **M1 — Deferred-Post-Extraction nicht in `packagePostProcessTasks`** (download-manager.ts:11974). Scheduler-Abschluss (8154) + finishRun (12310) sehen Deferred-Tasks nicht → Run-Ende/Summary feuert während noch Dateien verschoben werden, State-Reset mitten in FS-Arbeit.
- [ ] **M2 — `blockAllPersistence` wird nach Backup-Import nie zurückgesetzt** (app-controller.ts:678). Weiterarbeiten ohne Neustart → `persistSoon` ist dauerhaft No-Op → bei hartem Crash alle Änderungen weg.
- [ ] **M3 — `cancelPendingAsyncSaves` wartet nicht auf laufenden Async-Save** (storage.ts:1064). I/O-Overlap beim Import (Datenintegrität durch Generation-Guard geschützt, nur Robustheit).
### NIEDRIG
- [ ] **N1 — Toter Code in `findReadyArchiveSets`** (download-manager.ts:10847). Unbedingtes `ready.add+continue` macht strengeren Disk-Fallback-Block (untracked-pending-Schutz) unerreichbar.
**Empfehlung:** H1 + H2 + M1 zusammen fixen (eine kohärente Härtung der Deferred-Pipeline). H3 ist klein & unabhängig. M2 trivial.
---
## B. FEATURES / UX-GAPS (nach Mehrwert/Aufwand)
App läuft headless auf Windows-Server → Nutzer sitzt nicht davor. Größte Lücke: keine Benachrichtigungen.
1. [ ] **Webhook/Push-Benachrichtigungen** (Discord/Telegram/ntfy) — SM. Bei Paket fertig/Fehler/Quota/Provider-down aufs Handy. Neuer `notifier.ts`, Hooks an Completion-Punkten. **Höchster ROI.**
2. [ ] **Fernsteuerung über bestehenden Debug-Server** (POST-Endpunkte) — SM. Server hat schon HTTP + Token-Auth, aber nur GET. POST `/control/add-links`, `/start`, `/stop` → vom Handy steuern.
3. [ ] **URL-Duplikat-Erkennung beim Hinzufügen** — S. History-`urls` existiert, wird aber nie geprüft → versehentliche Re-Downloads verschwenden Quota. Warnen: "3 Links bereits geladen".
4. [ ] **Vereinheitlichter Pre-Flight-Check + Bulk-Skip toter Links** — M. Vor Start Größe/Name/Online für ganze Queue, "alle offline überspringen"-Button.
5. [ ] **Speicherplatz-Vorabprüfung vor Start** — S. Aktuell keine Free-Space-Prüfung → Abbruch mitten im Download bei voller Platte.
6. [ ] **Konsolidierte Fehler-Ansicht** — M. Alle fehlgeschlagenen Items flach + Fehlertext + "alle erneut versuchen".
7. [ ] **Per-Provider-Statistik** — M. Rohdaten (`providerTotalUsageBytes`) existieren, werden nur nicht dargestellt. Welches Abo lohnt sich?
8. [ ] **Auto-Retry fehlgeschlagener Pakete nach Wartezeit** — SM. Quota/Cooldown-Fails am nächsten Tag automatisch neu versuchen.
9. [ ] **Plex/Jellyfin Library-Refresh nach MKV-Move** — S. Neue Folgen sofort sichtbar. Gleicher Hook wie #1.
10. [ ] **Watch-Folder für DLC/Link-Auto-Import** — M. Ordner überwachen → automatisch importieren+starten.
---
## C. DESIGN-MOCKUPS
4 Varianten in `design-mockups/` (index.html = Vergleich):
1. **Aurora** — verfeinerte Dark-Evolution (premium, vertraut, geringstes Risiko)
2. **Command** — Terminal/Ops-Dashboard (max. Dichte, Monospace, Status-LEDs)
3. **Vellum** — Light Editorial (warmes Papier, Serif, mutige helle Alternative)
4. **Nebula** — Neon/Synthwave (Magenta-Cyan-Glow, auffällig)
→ Nutzer wählt Richtung (oder Mischung).
---
## REVIEW / ERGEBNISSE (2026-05-23)
**Umgesetzt (v1.7.158):**
-**H1**`abortPostProcessing` aborted jetzt auch alle Deferred- + Hybrid-Controller (globaler Stop/Shutdown/clearAll/external). Keine FS-Race gegen Shutdown-Save mehr.
-**H2** — Hybrid-Post-Extract läuft über neue `packageHybridPostProcessControllers`-Map (Set pro Package), Controller SYNCHRON vor dem detached Promise registriert, `shouldAbort` an Rename + MKV-Collect durchgereicht. `abortPackagePostProcessing` + `clearAll` räumen die Map. Cancel/Reset stoppt jetzt laufende Hybrid-Arbeit.
-**M1** — neuer `hasAnyDeferredPostProcessPending()`; Scheduler-Abschluss + `finishRun`-Clear gaten darauf. `hasDeferredPostProcessPending` (per-Package, für package_done-Cleanup) prüft jetzt auch Hybrid. Run endet erst wenn Background-FS-Arbeit fertig.
-**H3**`validateDownloadedFileCompletion`: 0-Byte bei `stream-end``ok:false` (download_underflow), routet in den bestehenden Retry-Pfad. Regressionstest in `tests/download-completion.test.ts` (8 Tests).
-**N1** — toter Disk-Fallback-Block in `findReadyArchiveSets` + verwaiste `pendingItemStatus`-Map entfernt (verhaltensneutral).
**Bewusst NICHT umgesetzt (mit Begründung):**
- ⏭️ **M2** (`blockAllPersistence` nie zurückgesetzt) — der vom Report vorgeschlagene Reset wäre **unsicher**: nach Backup-Import ist die In-Memory-Session stale (Import schreibt nur auf Disk, lädt den Manager nicht neu). Ein Reset würde beim nächsten persist die restored Daten mit Stale-State überschreiben. `blockAllPersistence` ist absichtlich bis-Neustart. Sauberer Fix = In-Memory-Reload nach Import (größerer Umbau, separat).
- ⏭️ **M3** (`cancelPendingAsyncSaves` wartet nicht auf laufenden Save) — Report stuft selbst als reines I/O-Overlap ein; die Generation-Guard (storage.ts:1022) schützt die Datenintegrität bereits (stale Write wird verworfen). Kein Korrektheitsgewinn, daher kein Eingriff.
**Verifikation:** 30 Test-Dateien, 621 Tests grün. Build sauber. Advisor-Review vor Implementierung (fing H2-Falle: Hybrid-Controller nicht in die Deferred-Map legen, sonst killt `runDeferredPostExtraction` sie selbst).