Skip to content

Wait before retrying a download whose cache write failed (0.3.1) - #21

Merged
Colton127 merged 2 commits into
mainfrom
claude/write-failure-retry-delay
Nov 8, 2026
Merged

Colton127 merged 2 commits into
mainfrom
claude/write-failure-retry-delay

Conversation

@Colton127

@Colton127 Colton127 commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner

When a write to the partial cache file fails, for example on a full disk, a retained download no longer requests the source again at once. It now waits 5 s before the next attempt, doubling up to a minute while attempts keep failing.

Changes

  • HttpCacheStream.download() counts attempts in a row that ended on an error, meaning an onError reported after the last onPosition.
    • A retained stream waits _retryDelay(n) after such an attempt: 5, 10, 20, 40, then 60 s.
    • An attempt that ends cleanly resets the count.
    • The catch path keeps its 5 s delay and now continues, so it doesn't wait twice.
  • CHANGELOG ## 0.3.1 Fixes entry, and the version goes to 0.3.1. 0.3.0 is already on pub.dev, so its section loses the (unreleased) label.

Why

BufferedIOSink.flush keeps its failed future, so CacheDownloader cancels. The Downloader loop then exits without its own 5 s delay, and download()'s while (true) loop started a new HTTP attempt immediately. Every attempt reported an error.

On a device whose storage is full, a stream kept requesting its source again and again for as long as it was retained. That costs mobile data, battery and a flood of reported errors.

Tests

  • New test/e2e/write_failure_test.dart blocks the partial file with a directory where the file goes:
    • the failed write is reported, and the origin sees one request in 3 s. Without the fix it sees 1389;
    • once the blocker is removed, the attempt after the wait completes the download, for two requests in all.
  • Full suite: 147 tests pass. dart analyze lib test is clean.

…g to a minute

When a write to the partial cache file fails (a full disk), BufferedIOSink.flush
keeps its failed future and CacheDownloader cancels. The Downloader loop then
exits without its 5 s delay, and download()'s while (true) loop started a new
HTTP attempt at once: 1389 requests in 3 s to a loopback origin in the new test.

download() now counts attempts in a row that ended on an error (one onError
reported after the last onPosition). A retained stream waits 5 s after such an
attempt, doubling to 60 s; an attempt that ends cleanly resets the count.

test/e2e/write_failure_test.dart blocks the partial file with a directory: one
request in 3 s, and once the blocker is removed the attempt after the wait
completes the download.
0.3.0 is on pub.dev, so its section loses the (unreleased) label.
@Colton127
Colton127 merged commit 5aa0cc3 into main Nov 8, 2026
2 checks passed
@Colton127
Colton127 deleted the claude/write-failure-retry-delay branch November 8, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant