docs(specs): take the cache fallback when an S13 drain fails
💡 What
Amends S13 (virtual-remote-foundation) so a virtual read that drains the winner's body before writing any response header treats the fetch and the drain as one fetch. A transport failure during that drain takes the cache fallback on the winner's position, otherwise UpstreamUnavailable.
Drain-first reads include a cold OCI blob HEAD, a cold ranged GET, a cold manifest GET, and a cold Maven maven-metadata.xml. Before this MR, S13 had a failed drain propagate to the slice, so no cached copy was served.
📝 Changes
-
Winner fetch failure: the boundary moves from "the fetch returned a body" to "the first response header is written". Before it, cache fallback or
UpstreamUnavailable. After it, the failure propagates. -
New subsection, A drain before any header is part of the fetch: the resolution layer runs the fallback, not the format slice. Which drain failures qualify:
Drain failure Answer Upstream transport failure, read-time size caps included Cache fallback, else UpstreamUnavailableLocal failure writing or committing the cache fill Reaches the slice unchanged, no fallback Digest check fails Reaches the slice unchanged, no fallback The caller's own context ends Abandonment: no fallback, no response Coalescing failure (leader cancelled by its client, follower wait timeout) Unchanged: 503 with Retry-After: 1Coalesced follower whose leader panicked Cache fallback, as on a failed fetch call -
Cache fallback on upstream failure and Resolution error surface: reworded to the same boundary. The
CacheFill-wrapped failures now include the commit of the cache fill that ends a drain. -
Acceptance Criteria, Error Cases, Resolutions: new criteria and rows for the drain cases, plus a Resolutions entry recording why the drain takes the fallback.
🚫 Out of scope
- S30, S31, and S32 still say "before any byte is streamed" for the winner's transport failure, in prose and, for S30 and S32, in their Acceptance Criteria and Error Cases rows. S32's rows link to the
#winner-fetch-failureanchor, which still exists. Each spec gets its own update to the new boundary. - The format-side changes in S30 and S32 are not part of this MR.
- The resolver code that runs the fallback on a drain failure follows in its own MR after this spec merges.
Related to #1430 (closed)