feat(remote): standalone remote request flow (S13 Step 11, part 2/3)
📦 What this MR does
Part 2 of 3 of S13 virtual/remote foundation — Step 11: standalone remote request.
This step is split into 3 stacked MRs to keep each within the review size limit (~800 reviewable LoC). Each part targets the previous one (part 1 targets main); review and merge proceed bottom-up.
This part is the flow itself: Standalone (standalone.go) composes Lookup, the RevalidationFor freshness verdict, the unhealthy-remote gate, and the coalesced Fetch into the kind=2 standalone serve flow, on the taxonomy and classification foundations from part 1/3.
- A fresh hit serves from the store with no upstream call, recording
last_downloaded_atoff the request path (fire-and-forget on a detached, bounded context). - A stale hit revalidates with its stored ETag; a miss (and a stale row without an ETag) fetches in full.
- An upstream refusal (any non-2xx except 304) propagates verbatim as
UpstreamReportsError; a success-shaped response the fetch rejected is classified as no-usable-response instead. - A transport failure serves any cached copy under the S13 cache-fallback rule, reported as
ServeFromCacheDegraded(with the served-from-cache-on-error log line) so a caller can tell it from a healthy cache serve, and returnsErrUpstreamUnavailableonly when none exists. - A leader loss under coalescing (
ErrLeaderCanceled, or its race twin, a synchronous followerErrFillAbandoned) is retried exactly once; a 304 serve re-reads the cache row rather than trusting the caller's pre-fetch snapshot; a vanished blob recovers with exactly one unconditional re-fetch on every path. - An unhealthy
last_health_statusblocks only the fetch paths withErrRemoteUnhealthy; a health-status read error is inconclusive — logged throughlogDegradedInfra, the fetch proceeds.
🎯 Spec coverage
This part carries one core acceptance test per spec behavior; the deeper concurrency-choreography and edge-case suite lands in part 3/3.
| Spec behavior | Test |
|---|---|
| Fresh hit serves from cache; no upstream call, no health read | TestStandalone_Serve_FreshHitServesFromCache |
| Fresh-hit download record survives client disconnect | TestStandalone_Serve_FreshHitBumpSurvivesRequestCancellation |
| Fresh-hit download-record failure never fails the serve | TestStandalone_Serve_FreshHitBumpFailureStillServes |
| Stale hit revalidates with stored ETag; 304 serves the cached blob | TestStandalone_Serve_StaleHitRevalidates304 |
| Stale hit, etag differs: 200 refills the row and stores the new validator | TestStandalone_Serve_StaleHitETagDiffersRefills |
| Stale hit, no stored ETag: re-fetched in full, no validator sent | TestStandalone_Serve_StaleHitWithoutStoredETagFetchesFull |
| Miss streams and fills; standalone issues GET only | TestStandalone_Serve_MissStreamsAndFills |
| Standalone status fidelity: non-2xx propagates verbatim | TestStandalone_Serve_UpstreamStatusPropagatesVerbatim |
| Success-shaped response the fetch rejected is no-usable-response, not a verbatim status | TestStandalone_Serve_UnusableSuccessShapedResponseServesFallback, TestStandalone_Serve_UnusableSuccessShapedResponseWithoutCacheEntryFails |
| Transport failure with a cache entry serves fallback + log line | TestStandalone_Serve_TransportFailureServesFallback |
Transport failure with no cache entry returns ErrUpstreamUnavailable |
TestStandalone_Serve_TransportFailureWithoutCacheEntryFails |
| Direct request to unhealthy remote blocks the fetch paths | TestStandalone_Serve_UnhealthyRemoteBlocksFetchPaths |
| Health-status read error is inconclusive; the fetch proceeds and is logged | TestStandalone_Serve_HealthReadErrorDoesNotBlockFetch |
📖 References
🧪 E2E scenario catalog
No scenario added or affected: this is service-layer composition with no HTTP endpoint. The format handlers that expose the standalone flow will add the client-visible scenarios.
:bricks: Stacked MRs (review/merge bottom-up)
- feat(remote): serve taxonomy, transport marker,... (!1290 - merged) • David Fernandez • 19.3
- feat(remote): standalone remote request flow (S... (!1291 - merged) • David Fernandez, Dzmitry (Dima) Meshcharakou • 19.3
👈 - fix(remote): standalone serve suite and upstrea... (!1292 - merged) • David Fernandez, Dzmitry (Dima) Meshcharakou • 19.3
Related to #332 (closed)