Régression introduite par v0.28.11 (durability checkpoint) : le footer
affichait des pourcentages > 100% en fin de DL, même sans pause manuelle.
Cause : seg.DownloadedBytes était devenu durable (incrémenté au checkpoint
tous les 64 MiB), MAIS onBytes(seg.Index, n) continuait à fire par
WriteAsync. Quand Polly retry un segment mid-stream (fréquent sur OVH
mutualisé qui coupe les requêtes longues via PHP-FPM
request_terminate_timeout) :
Attempt 1 :
- onBytes fire pour bytes 0..30 MiB (live)
- HttpResumableException (PHP-FPM kill)
- Dispose flush, mais seg.DownloadedBytes encore à 0 (dernier checkpoint)
Polly retry attempt 2 :
- segStart = seg.Start + 0
- Re-download bytes 0..30 MiB (overwrite same content sur disque, OK)
- onBytes fire À NOUVEAU pour ces 30 MiB ← DOUBLE COMPTAGE
Multiplié par 16 segments × N retries → aggregate dépasse total.
Fix : onBytes fire UNIQUEMENT au checkpoint, avec la valeur inFlight
juste avant la reset. Comme ça les bytes d'une attempt qui a failé ne
sont jamais reportés (la failure se produit AVANT que le checkpoint
soit atteint), et la retry re-télécharge + reporte une seule fois.
Trade-off : UI updates tous les 64 MiB par segment au lieu de chaque
4 MiB. Avec 16 segments en parallèle, ça fait ~10-20 reports/s en pic,
le reporter task échantillonne à 4 Hz de toute façon, invisible côté UX.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.9 KiB
4.9 KiB