docs(specs): take the S32 cache fallback on a failed drain

What

S32 now states that a failed drain takes the cache fallback. A manifest pull, a HEAD, and a ranged GET drain the winner's body before they write any response header. A transport failure or a read-time size-cap breach during that drain serves the winner position's cached copy, and answers 503 UNAVAILABLE where that position holds none. A digest mismatch the drain finds still serves no cached copy.

S32 also now matches S13 on which cache a failed winner falls back to: the winner's own position, not any consulted position.

Why

#1430 (closed) decided that the boundary between "before" and "after" a winner's stream is the first response header, not the resolver returning the body. It also decided that the fallback reads only the winner's own cache, which is what serveFallback does today. S32 said "before any byte is streamed" and "a cached copy from a consulted position", so both needed to move with S13.

What changed

  • ## Dependencies: the S13 row records !2912 (merged) as the amendment that brought the first-header boundary and the winner-only drain fallback.
  • ### Container virtual resolution: a paragraph for a winner that fails before any header, outside the no-winner list, and a paragraph that states the drain rule and names the stale tag refetch as the read that reaches the cached copy.
  • ## Acceptance Criteria, ### Resolution: one criterion for a failed drain, cold and on a stale tag. The transport criterion and the drain criterion rule out a copy at any other position, higher or lower. The by-digest criterion tells the two winner failures apart by Retry-After and digest_mismatch, and the tag-addressed criterion carries the served-copy difference.
  • ## Error Cases: the transport-failure rows use the first-header boundary and name the failed drain. New or widened rows cover a follower whose leader panicked, a leader whose client disconnected, and a drain the caller abandoned.
  • ### Wide events: a winner's failed Fetch or drain records served_from_cache when it serves its own cached copy, and unavailable when it holds none, with the winner_* fields present. served_from_fallback stays the no-winner branch's value.

Merge order

!2912 (merged), the S13 amendment for #1430 (closed), has merged, and this branch merges main after it.

The code follows in two parts:

  • a foundation MR with the resolver entry point for the fallback
  • a follow-up to the S32 serve (!2900 (merged)) that calls it from drainFill

!2900 (merged) already answers 503 for a failed drain with nothing cached.

Related to #1430 (closed)

🤖 Generated with Claude Code

Edited by Radamanthus Batnag

Merge request reports

Loading
Loading