Fix: festes Retry-Limit wird jetzt hart eingehalten — kein Endlos-Shelve-Loop mehr (Runde-6-Audit)

Bei einem FESTEN retryLimit (>=5) sind alle drei Per-Klasse-Retry-Caps
(stall/unrestrict/generic) gleich dem Limit. Die beiden "15-Fehler"-Shelve-Zweige
(download-manager.ts stall-Pfad + error-Pfad) feuern aber auf der hartkodierten
Summe >=15 OBERHALB der Per-Klasse-Terminal-Fail-Pruefungen und HALBIEREN danach
alle drei Zaehler. Dadurch wurden die Per-Klasse-Caps nie gleichzeitig
ueberschritten: der Eintrag erreichte nie status="failed", schliff endlos im
90s-Takt, item.retries wuchs weit ueber das konfigurierte Limit, der
Download-Slot blieb dauerhaft belegt, und das wiederholte
providerFailures.delete besiegte immer wieder den Provider-Circuit-Breaker →
Hoster-Hammering. resetStaleRetryState konnte nicht eingreifen, weil der
<=90s-Re-Admit item.updatedAt frisch haelt (nie 10min stale).

Der Auslieferungs-Default retryLimit=0 (= unendlich) ist NICHT betroffen — dort
ist der 15-Fehler-Shelve der gewollte Dauer-Park-Backstop und es gibt kein
endliches Budget zu verletzen.

Fix: in BEIDEN Shelve-Zweigen vor dem queueRetry eine harte Obergrenze —
`if (configuredRetryLimit > 0 && item.retries >= configuredRetryLimit)` failt den
Eintrag terminal (status="failed", recordRunOutcome, retryStateByItem.delete)
statt ihn neu zu queuen. Der ∞-Modus (retryLimit<=0) ueberspringt die Grenze und
bleibt unveraendert.

Runde-6-Audit (adversarisch verifiziert) hat ausserdem den deferred-LOW-Cluster
abgeschlossen: #10 HTTP416-shared-counter, #11 fresh-retry-preempt und #13
queue-wait→elapsedMs sind BENIGN; #12 war genau dieser Bug.

Rot-bewiesen: Single-Pass-Integrationstest seedet genericErrorRetries=15 vor und
injiziert einen generischen Fehler bei retryLimit=5 → ohne Fix requeued der
Shelve (status bleibt nicht "failed"), mit Fix wird terminal gefailt. Volle Suite
882 gruen, tsc unveraendert.
This commit is contained in:
Sucukdeluxe
2026-06-17 10:58:18 +02:00
parent e49ed1ada0
commit d2a1b831a0
4 changed files with 103 additions and 0 deletions
+20
View File
@@ -161,6 +161,26 @@ RELEASE BEWUSST AUFGESCHOBEN: beide MED/LOW (kein HIGH wie 216/217) → buendeln
Retries ueberlastet → kein Sign-off fuer den Mega-Park-Hot-Path-Klassifikations-Change. Fixes sind
durable. Plan: Runde 6 dazu buendeln, Advisor-Sign-off abwarten, dann v1.7.218 als Roll-up.
## Runde 6 (Retry/Backoff/Error-Klassifikations-State-Machine + Disk/IO) — Workflow wqurq83ma
3 Finder + adversarisch verifizieren. 1 confirmed (2/3), 3 refuted. Schliesst den deferred-LOW-Cluster ab.
- **CONFIRMED HIGH (GEFIXT) SHELVE-LOOP-RETRYLIMIT:** Bei FINITEM retryLimit>=5 sind alle drei Per-Klasse-
Caps = retryLimit; die 15-Failure-Shelve-Zweige (dl-mgr 9166 stall + 9352 error) feuern aber auf
hartkodiertem `sum>=15` OBERHALB der Per-Klasse-Terminal-Fails und HALBIEREN danach alle Counter →
Per-Klasse-Caps werden nie gleichzeitig ueberschritten → Item failt NIE, schleift ewig, item.retries
waechst ueber das konfigurierte Limit, Slot gestrandet, providerFailures.delete besiegt wiederholt den
Circuit-Breaker → Hoster-Hammering. resetStaleRetryState rettet nicht (<=90s-Re-Admit haelt updatedAt
frisch < 10min-Stale). Default retryLimit=0=∞ NICHT betroffen (Shelve ist dort der gewollte Park-Backstop).
Fix: in BEIDEN Shelve-Zweigen vor dem queueRetry `if (configuredRetryLimit > 0 && item.retries >=
configuredRetryLimit)` → terminal failen statt requeue (∞-Modus unberuehrt). Rot-bewiesen (Single-Pass-
Integrationstest: genericErrorRetries=15 vorgeseedet + injizierter Generic-Error → status "failed" statt
requeue). tsc=6.
- **Deferred-LOW-Cluster re-klassifiziert (aus Runden 1-2):** #10 HTTP416-shared-counter BENIGN (maxHttp416Retries
eigenes Budget, speist Shelve-Summe NICHT); #11 fresh-retry-preempt BENIGN (One-Shot-Booleans);
STALL-CAP-OFF-BY-ONE real aber +1 (Zutat von CONFIRMED-1, kein eigener Strand); #13 queue-wait→elapsedMs
BENIGN (queueRetry resettet attempts/updatedAt, Stall-Detektor misst nur aktiven Download). #12 = der
gefixte Bug. DISK-1 (ENOSPC/EACCES via Generic-Budget) kein eigener Bug (in finite vom Cap + diesem Fix
begrenzt; in ∞ by-design) → optionale Klassifikations-Erweiterung, deferred bis Nutzer Full-Disk-Hammering meldet.
## Runde 5 (unberuehrte Subsysteme: auto-reconnect, Scheduler-Fairness, Crash/Persistenz) — Workflow w7woztsxx
3 Finder (reconnect / scheduler / persistence) → adversarisch verifizieren (3 Lenses). 1 Kandidat, 0 confirmed.
**Sauberes „kein bestaetigter Bug"-Ergebnis.** Auto-reconnect-Resume, Slot-Accounting/Fairness und