Fix: Mega-Web Selbst-Cooldown bei belegter Queue + Legacy-Config Mega-Demotion (Audit Runde 9+10)
MW-1 (HIGH): Ein gesunder Mega-Web-Account wurde 120s gesperrt, wenn der
60s-Gesamttimeout ablief, waehrend die Umwandlung noch SERIELL in der
per-Account-Single-Flight-Queue auf ihren Vorgaenger wartete - also bevor echte
Arbeit begann. Die Queue-Wartezeit zaehlte zu elapsedMs (>= 8s), sodass der
Abbruch faelschlich wie ein In-Arbeit-Abbruch eines langsamen Accounts gewertet
wurde. Genau die gemeldete 'Tool sperrt sich selbst'-Klasse (Web-Variante).
Zweiteilig: (1) MegaWebFallback.runExclusive trackt workStarted und meldet einen
Abbruch-vor-Arbeitsbeginn als Queue-Timeout statt aborted:mega-web;
(2) unrestrictViaWeb bewahrt diese Klassifikation statt sie zu aborted:debrid zu
plaetten -> die Rotation trifft die Queue-Timeout-Ausnahme (cooldownMs 0) statt
den Abbruch-Cooldown. Ein echter In-Arbeit-Abbruch sperrt weiterhin (langsame
Accounts korrekt ueberspringen). Nach dem No-Cooldown-Pfad rotiert der Retry per
In-Flight-Tiefe auf einen freien Account.
SET-MIG-01 (MED): Eine Config von vor v1.6.90 kannte die getrennten
Mega-API/Web-Enable-Flags nicht. readSettingsFile merged {...defaultSettings(),
...parsed}, also fuellten die false-Defaults die fehlenden Flags BEVOR
normalizeSettings lief -> der creds-basierte Migrationszweig war tot, Mega blieb
auf aus trotz vorhandener Creds und wurde beim ersten Settings-Save still aus der
providerOrder demotet. Fix: reine migrateLegacyMegaEnableFlags seedet die Flags
nur, wenn BEIDE im RAW-parsed fehlen und Creds vorhanden sind (absent-both als
einziger sicherer Trigger; present-false bleibt unberuehrt = bewusst-deaktiviert
nicht re-aktivieren). Greift nur bei Legacy-Configs, die seit dem Upgrade noch
nicht neu gespeichert wurden.
Je rot-bewiesener Test (per Temp-Revert verifiziert, nicht-vakuum). Volle Suite
890 gruen, tsc unveraendert (6 vorbestehende Fehler). Runde-9/10-Doku + die zwei
offenen Nutzer-Entscheidungen aktualisiert.
This commit is contained in:
@@ -10,6 +10,116 @@ Backup/Restore, account-check) → Abschlussbericht + Ende. Fixes je rot-bewiese
|
||||
Disziplin: erst BELEGEN (Code-Zitat + konkretes Szenario), dann adversarisch verifizieren,
|
||||
dann TDD-Fix. Kein Blind-Fix. Tests gruen + tsc=6 nach jeder Runde. Periodisch releasen.
|
||||
|
||||
## Runde 9 (Provider-spezifische Unrestrict-/Rotations-Pfade) — Mega-Web-Single-Flight + DebridLink-Key + Concurrency
|
||||
Fokus: Mega-Web-Fallback Session/Single-Flight-Queue, DebridLink-Key-Rotation, In-Flight-Verteilung.
|
||||
- **CONFIRMED HIGH (GEFIXT) MW-1 Selbst-Cooldown eines GESUNDEN, nur in der Queue wartenden Web-Accounts:**
|
||||
Der Caller-Timeout (`DEFAULT_UNRESTRICT_TIMEOUT_MS`=60s) feuert, waehrend die zweite Umwandlung eines
|
||||
Accounts noch SERIELL in der Mega-Web-Single-Flight-Queue (90s `QUEUE_WAIT_TIMEOUT_MS`) auf den laufenden
|
||||
Vorgaenger wartet — also bevor ueberhaupt echte Arbeit begann. `raceWithAbort` warf bisher unbedingt
|
||||
`aborted:mega-web`; `unrestrictViaWeb` (debrid.ts:1887) flachte JEDEN signal-aborted-Fall zu `aborted:debrid`
|
||||
ab; die Rotation (debrid.ts:2072) wertete das via `/aborted/i && !/timeout/i` → `ranLongEnough`
|
||||
(elapsedMs schliesst die Queue-Wartezeit ein, also >= 8s) → **120s Account-Cooldown auf einen voellig
|
||||
gesunden Account**. Genau die vom Nutzer gemeldete „Tool sperrt sich selbst"-Klasse (Web-Variante).
|
||||
Zweiteiliger Fix:
|
||||
(1) `MegaWebFallback.runExclusive` (mega-web-fallback.ts) trackt `workStarted` und reicht eine
|
||||
`abortErrorFactory` an `raceWithAbort`: abgebrochen-bevor-Arbeit-begann → `Mega-Web Queue-Timeout (…)`
|
||||
(matcht `/queue.?timeout/i`), nur ein echter In-Arbeit-Abbruch bleibt `aborted:mega-web`.
|
||||
(2) `unrestrictViaWeb` (debrid.ts:1887) bewahrt einen `/queue.?timeout/i`-klassifizierten lastError statt
|
||||
ihn zu `aborted:debrid` zu plaetten → Rotation trifft die bestehende Queue-Timeout-Ausnahme
|
||||
(classifyAccountFailure 2243 → cooldownMs 0) statt den Abbruch-Cooldown-Zweig.
|
||||
Rot-bewiesen NICHT-vakuum (zwei Tests, beide per Temp-Revert rot verifiziert):
|
||||
- Teil 1 (mega-web-fallback.test.ts): echtes `MegaWebFallback`, Queue mit langsamem Erst-Job belegt,
|
||||
Zweit-Call WAEHREND in Queue abgebrochen → `rejects.toThrow(/queue.?timeout/i)` (ohne Fix: `aborted:mega-web`).
|
||||
- Teil 2 (debrid.test.ts): durch `DebridService.unrestrictLink` mit `RD_MEGA_ABORT_MIN_RUN_MS=0` (besiegt die
|
||||
Vakuum-Falle: der buggy Pfad WUERDE selbst bei Sofort-Abbruch cooldownen), Signal bricht WAEHREND des
|
||||
Calls ab, megaWeb meldet Queue-Timeout → `getMegaDebridAccountCooldownState` bleibt null (ohne Fix: 120s
|
||||
„Abbruch/Timeout nach 0s"). tsc=6, volle mega-web+debrid-Suite 103 gruen inkl. der bestehenden
|
||||
Abbruch-Cooldown-Tests (echter langsamer Account cooled WEITERHIN — keine Regression).
|
||||
- **Rotations-Verifikation (Advisor-Shippability-Diskriminator):** Nach dem No-Cooldown-Pfad retried der
|
||||
Manager `unrestrictWithAccounts` frisch. Die Account-Wahl sortiert per `megaDebridInFlight`-TIEFE
|
||||
(debrid.ts:1981-1986, least-busy zuerst). Invariante: jeder Belegt-Halter der MegaWebFallback-Queue
|
||||
entspricht einem in-flight `client.unrestrictLink`, das `megaDebridInFlight` inkrementiert hat (2033,
|
||||
Dekrement nur im finally 2152). Also sieht der Retry des queue-getimeouteten Links den saturierenden
|
||||
Account bei Tiefe>=1 und rotiert auf einen freien — MW-1 ist NACHWEISLICH besser als das alte 120s-Lockout
|
||||
(das einen nur-belegten gesunden Account sperrte). Kein Tight-Retry-Loop auf saturierter Queue, solange
|
||||
irgendein Account frei ist; sind ALLE saturiert, queued der least-busy (unvermeidbar — keine freie Kapazitaet,
|
||||
aber das alte Cooldown haette es via Faux-Park SCHLIMMER gemacht).
|
||||
- **DOKUMENTIERT, nicht gefixt (LOW) DL-1 DebridLink-Key-Cooldown bei User-Cancel-Abbruch:** classifyKeyFailure
|
||||
(debrid.ts:3118-3126) gibt fuer Text mit „aborted" (via isRetryableErrorText 597 + isTransport 3119)
|
||||
`cooldownMs: 15_000` zurueck — auch bei einem SCHNELLEN User-Cancel (kein Min-Run-Gate wie bei Mega 2072).
|
||||
Symptom: 15s Key-Cooldown nach Nutzer-Abbruch. Advisor (revidiert eigenen frueheren „clean fix"-Call):
|
||||
classifyKeyFailure hat KEIN elapsedMs und DebridLink hat keinen Min-Run-Knopf-Aequivalent zu
|
||||
`getMegaDebridAbortMinRunMs()`. Der treue Fix (Caller-Gate bei 2787 spiegeln) braucht entweder cross-Provider-
|
||||
Wiederverwendung des Mega-Knopfes oder einen neuen DebridLink-Knopf = neue Oberflaeche im Live-Hot-Path fuer
|
||||
einen LOW-Bug (Symptom: 15s nach User-Cancel). Klart die eigene „clean + null-Regression"-Schwelle NICHT →
|
||||
dokumentiert, nicht gefixt.
|
||||
- **DOKUMENTIERT, nicht gefixt (MED) DL-CONCURRENCY-PILEUP:** Bei gleichzeitigen Umwandlungen, die ALLE
|
||||
Mega-Accounts saturieren, queued der least-busy-Account weitere Links seriell (per-Account-Single-Flight) →
|
||||
Wartezeiten stapeln sich. MW-1 entfernt die FRUEHERE versehentliche Backpressure (der falsche 120s-Cooldown
|
||||
wirkte als grobe Ratenbegrenzung), routet aber korrekt per In-Flight-Tiefe um belegte Accounts herum statt sie
|
||||
faelschlich zu sperren — strikt besser. Echter Fix (In-Flight-Tiefen-Spread groesser ziehen / globale
|
||||
Web-Parallelitaetsgrenze) = groessere Aenderung, 4.-Bug-Risiko auf Live-Server → deferred. MW-1 reduziert das
|
||||
Pileup-in-Park-Risiko bereits (kein Faux-Lockout merely-busy Accounts).
|
||||
|
||||
## Runde 10 (Concurrency/Locking + Settings/Persistenz-Integritaet) — LETZTE RUNDE (Nutzer: „nach der Runde ist Schluss")
|
||||
4 Finder (hybrid/targetPath-Races, Slot-Accounting, Settings-Migration/Persistenz, Backup-Restore/account-check)
|
||||
→ adversarisch 3 Lenses → Synthese. Workflow wwyqsdrf9: 2 Finder (slot-accounting, settings-persistence) starben
|
||||
an Stream-Idle-Timeout (Riesen-Dateien) → 0/7 confirmed war NUR fuer 2 von 4 Dimensionen ehrlich. KEIN stilles
|
||||
Coverage-Loch akzeptiert → Re-Run wwyqsdrf9b (wfmu4pw2n) mit engerem Scope (Grep-dann-Region statt Ganzdatei).
|
||||
- **Dim hybrid/targetPath + backup/account-check (wwyqsdrf9): 7 Kandidaten, ALLE refutiert (>=2/3), quell-reverifiziert.**
|
||||
Kern-Invarianten halten: synchrones `claimTargetPath` (dl-mgr:6257) = nie zwei Items auf einem Pfad → alle drei
|
||||
Hybrid-„Races" kollabieren zu Sub-Sekunden-Redundanzarbeit, kein Collision/Korruption; jeder Loss-Ausgang von
|
||||
CRC/Extraction-Fail re-queued (`hybridExtractRequeue.add` 11739). Restore ist fail-closed (encrypted-or-reject,
|
||||
Binaerheader „MDD1" wirft in JSON.parse vor normalizeSettings). account-check `valid:false` ist reiner
|
||||
Renderer-Badge (kein src/main liest ihn als Gate; Disable laeuft ueber megaDebridDisabledAccountIds).
|
||||
- **CONFIRMED MED (DOKUMENTIERT, nicht gefixt) BYTE-DROP-RETRY-1 (wfmu4pw2n):** Integrity-/too-small-/tiny-Retry
|
||||
doppelzaehlt eine volle Datei in die Byte-Statistik. `dropItemContribution` (6247) loescht den
|
||||
itemContributedBytes-Eintrag OHNE von session.totalDownloadedBytes abzuziehen (eigener Kommentar: „retry path
|
||||
subtracts on its own"), aber die EINZIGE Subtraktion (9991-9997) liest genau diesen geloeschten Eintrag → 0 →
|
||||
Subtraktion tot → Re-Download addiert N nochmal → (k+1)*fileSize nach k Integrity-Fails. enableIntegrityCheck
|
||||
default true → organisch. Verdict isReal (CORRECTNESS+REPRO), aber BLAST-RADIUS = NUR Statistik: kein
|
||||
Slot/Admission/Semaphore liest diese Counter (grep-belegt), Session-Counter self-healen bei jedem Neustart,
|
||||
nur persistiertes totalDownloadedAllTime + avg-Speed bleiben dauerhaft inflationiert = kosmetisch. NICHT clean
|
||||
(dropItemContribution ueber 26 Call-Sites ueberladen; ~10 im Retry-Bereich; ein 3-Site-Patch liefert
|
||||
partielles/inkonsistentes Accounting = arguably schlimmer; Guard-Test dl-mgr.test.ts:6152 sperrt die
|
||||
Completion-Removal-Semantik) → DOKUMENTIERT mit Rezept (dropItemContribution splitten in ForCompletion/ForRetry
|
||||
nach Klassifikation aller Retry-Sites re-download-vs-terminal). Kosmetisch + nicht-clean → klart Live-Schwelle nicht.
|
||||
- **CONFIRMED MED (GEFIXT) SET-MIG-01 (wfmu4pw2n):** Pre-v1.6.90-Config-Migration tot → Mega-Debrid wird beim
|
||||
ersten Settings-Panel-Save still aus der Provider-Reihenfolge demotet. readSettingsFile (storage.ts:633) merged
|
||||
`{...defaultSettings(), ...parsed}`; defaultSettings setzt megaDebridApiEnabled/WebEnabled:false (constants.ts:50-51)
|
||||
BEVOR normalizeSettings laeuft → der `=== undefined`-Migrationszweig (355-360) ist tot auf dem Disk-Pfad (Git:
|
||||
tot seit v1.6.90/0003d78). Renderer (App.tsx:447-494) gated Mega-Inklusion am false-Flag → persistDraftSettings
|
||||
schreibt eine Mega-bereinigte providerOrder zurueck. Fix: reine `migrateLegacyMegaEnableFlags(parsed)` in
|
||||
readSettingsFile — seedet apiEnabled=preferApi/webEnabled=!preferApi NUR wenn BEIDE Flags im RAW-parsed fehlen
|
||||
UND Creds da sind (Creds-Erkennung wie normalizeSettings: asText(login)&&asText(password)). Lokalisiert, keine
|
||||
normalizeSettings-Signatur-Aenderung, getypt (kein Cast). EHRLICHER Scope (Advisor): rettet NUR Legacy-Configs,
|
||||
die seit dem Upgrade noch NICHT ueber das Settings-Panel neu gespeichert wurden (ein Post-Upgrade-Save schreibt
|
||||
present-false → Trigger feuert nicht mehr) — schmales historisches Fenster, NICHT „rettet die Live-Mega dieses
|
||||
Nutzers". HARTE Grenze (Advisor): Trigger bleibt absent-both; present-false NICHT anfassen (= bewusst-deaktiviert,
|
||||
ununterscheidbar → das geparkte entscheidungen-offen #2-Migrationsrisiko). Rot-bewiesen NICHT-vakuum (Assertion NUR
|
||||
auf den geladenen Flags — providerOrder demotet backend-seitig nicht = waere vakuum; via Temp-Revert rot bestaetigt:
|
||||
apiEnabled true→false). Boundary-Test (bewusst-deaktiviert bleibt false + ohne Creds keine Migration) bleibt beim
|
||||
Revert gruen = unabhaengig. Volle Suite 890 gruen, tsc=6.
|
||||
- **REFUTED (wfmu4pw2n) SET-PERSIST-02:** Residual-Lost-Update nach R2-Generations-Guard — der einzige verlorene
|
||||
Payload ist totalRuntimeAllTimeMs (`<=`-Ratchet, naechste Session re-derived) + contrived Sub-ms-Race der die
|
||||
Prozess-Teardown gewinnen muss → self-healing kosmetisch, nicht erreichbar.
|
||||
- **Coherence-Verdikt:** Concurrency-Accounting + Settings-Persistenz sind kohaerent. Byte-Counter sind
|
||||
telemetry-only, voll entkoppelt von Admission/Slot (grep-belegt) → BYTE-DROP kann nicht stranden/freezen/
|
||||
ueber-admiten. Persistenz kohaerent bis auf EINE benannte Inkohaerenz: Backend normalizeConfiguredProvider
|
||||
(storage.ts:144) mapt „megadebrid"→konkret unabhaengig der Flags, Renderer gated auf dem Flag = Wurzel von
|
||||
SET-MIG-01 (jetzt am Loader gefixt).
|
||||
- **EHRLICHE Coverage-Luecke (vom Audit selbst aufgedeckt, R10-HYB-3):** Die in project_pending genannte
|
||||
Passwort-Cache-Race liegt NICHT in download-manager.ts (dort kein passwordCache/resolvePassword), sondern in
|
||||
src/main/extractor.ts — ausserhalb des Round-10-Scopes. Bewusst NICHT in dieser letzten Runde auditiert (Nutzer:
|
||||
„nach der Runde ist Schluss"); als das eine identifizierte, un-auditierte Concurrency-Seam fuer eine etwaige
|
||||
kuenftige Runde dokumentiert statt still fallengelassen.
|
||||
|
||||
## GOAL-ABSCHLUSS
|
||||
Runde 9 + 10 erledigt (Nutzer-Anpassung). Release v1.7.220 buendelt: 85c8d6b (Synthese C1/C2/RANGE1-Haertung) +
|
||||
MW-1 (HIGH, Web-Selbstcooldown) + SET-MIG-01 (MED, Legacy-Mega-Demotion). Gitea + GitHub-Mirror MIT .exe (4 Assets).
|
||||
Dokumentiert-nicht-gefixt: DL-1, DL-CONCURRENCY-PILEUP, BYTE-DROP-RETRY-1, extractor.ts-Passwort-Cache-Seam.
|
||||
Beim Nutzer (nicht autonom): 60s-Failover-Kappung + gespiegelter Mega-API/Web-Schalter (entscheidungen-offen.md).
|
||||
|
||||
## Runde 1 (laeuft)
|
||||
- Discover+Verify-Workflow ueber 7 Subsysteme (scheduler-slots, unrestrict-retry, mega-rotation,
|
||||
classify-cooldown, mega-web-token, provider-chain-timeout, account-availability).
|
||||
|
||||
@@ -63,6 +63,30 @@ ODER zwei unabhängige Pro-Modus-Schalter (mehr Kontrolle, aber UI + Migration n
|
||||
|
||||
## Erledigt in dieser Runde (zur Info, kein Handlungsbedarf)
|
||||
|
||||
- **Alte Konfiguration: Mega-Debrid fällt nach einem Upgrade nicht mehr still aus der Provider-Reihenfolge:**
|
||||
Eine Konfigurationsdatei, die noch von einer sehr alten Version (vor v1.6.90) stammt, kannte die getrennten
|
||||
Mega-Debrid „API aktiv"/„Web aktiv"-Schalter noch nicht. Beim Laden wurden diese fehlenden Schalter still auf
|
||||
„aus" gesetzt, obwohl Mega-Zugangsdaten vorhanden waren — und sobald man danach das erste Mal die Einstellungen
|
||||
speicherte, wurde Mega-Debrid dadurch lautlos aus der Provider-Reihenfolge entfernt. Jetzt wird beim Laden einer
|
||||
solchen alten Datei erkannt, dass die Schalter komplett fehlen, und Mega-Debrid passend zu deiner Bevorzugung
|
||||
(API oder Web) aktiviert — genau die Migration, die ursprünglich gedacht war, aber durch einen Default-Vorrang
|
||||
nie ausgelöst hatte. Ehrlicher Umfang: Das betrifft nur alte Dateien, die seit dem Upgrade noch NICHT über die
|
||||
Einstellungen neu gespeichert wurden — wer seit dem Update schon einmal in den Einstellungen gespeichert hat, hat
|
||||
die Schalter bereits als „aus" stehen und greift dort weiterhin manuell ein (das ist Absicht: ein bewusst auf
|
||||
„aus" gestellter Schalter wird NICHT wieder angeschaltet). Rot-bewiesener Test; voller Testlauf grün.
|
||||
|
||||
- **Mega-Web: gesunder Account sperrt sich nicht mehr selbst, nur weil er gerade belegt war (deine „Tool sperrt sich selbst"-Klasse, Web-Variante):**
|
||||
Wenn mehrere Links gleichzeitig über DENSELBEN Mega-Account umgewandelt wurden, laufen sie absichtlich nacheinander
|
||||
(eine Warteschlange pro Account, damit nicht doppelt eingeloggt/gehämmert wird). Wartete ein Link in dieser Schlange
|
||||
noch auf seinen Vorgänger und lief dabei der 60-Sekunden-Gesamttimeout ab, wurde der Abbruch fälschlich wie ein echter
|
||||
Account-Fehler gewertet → der völlig gesunde Account bekam 120 Sekunden Sperre. Jetzt wird ein Abbruch, der NOCH IN DER
|
||||
Warteschlange passiert (bevor echte Arbeit begann), als reiner Warteschlangen-Timeout erkannt: KEINE Account-Sperre,
|
||||
der Link wird einfach erneut versucht und rotiert dann von selbst auf einen freien Account. Ein echter Abbruch MITTEN
|
||||
in der Arbeit sperrt den Account weiterhin (damit langsame Accounts korrekt übersprungen werden) — das blieb unverändert.
|
||||
Zwei rot-bewiesene Tests (jeder ohne Fix nachweislich rot; der zweite läuft komplett durch die echte Account-Rotation
|
||||
und prüft, dass keine Sperre gesetzt wird). Die Rotation auf einen freien Account ist über die Auslastungs-Verteilung
|
||||
(am-wenigsten-belegter-Account-zuerst) abgesichert — strikt besser als die alte 120s-Pauschalsperre.
|
||||
|
||||
- **Stille Datei-Beschädigung beim Resume nach Verbindungsabbruch behoben (für Dateien mit bekannter Größe):**
|
||||
Wenn ein Debrid-Server beim Abbruch einen kleinen Fehler-Müll-Block mitten in den Datenstrom schreibt und
|
||||
das genau im LETZTEN Wiederhol-Versuch passierte, blieb dieser Müll in der Datei und der anschließende
|
||||
|
||||
Reference in New Issue
Block a user