Repository navigation
Confirm a recovered cache entry's version before serving it (ADR-0049) - #89
Merged
Merged
Conversation
The cache directory is a hostPath, so a restarted daemon rebuilds both disk tiers from the previous process's files: the chunk store from its slot headers, foyer from its blocks. Neither knows whether what it recovered is still current. An object overwritten while the node was down came back as its old bytes, and so did one overwritten through PACER just before a restart: ChunkStore::remove only updates the in-memory index, and foyer keeps no tombstone for a removed entry. A cached header is now used only once this process has confirmed its object against the backend, so the first read of each object after a restart costs one HeadObject. Every node-mode fill records the version it filled, and a chunk is served only under the ETag the read resolved: locally, from a peer, and by a holder's one-sided write into client memory, whose response now carries the holder's witness. A mismatched local copy is forgotten so its re-fill can land; a mismatched peer copy is skipped and its holder sent an Invalidate. ETags are compared without quotes, because the scatter path tags chunks with CompleteMultipartUpload's quoted one. tests/daemon/restart.rs restarts a daemon over its own cache directory on both tiers: an overwrite while down, an invalidation before the restart, and an unchanged object, which must still be served from the recovered tier after one HeadObject and no re-fill. Fixes #64 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The cache directory is a hostPath, so a restarted daemon rebuilds both
disk tiers from the previous process's files: the chunk store from its
slot headers, foyer from its blocks. Neither knows whether what it
recovered is still current. An object overwritten while the node was
down came back as its old bytes, and so did one overwritten through
PACER just before a restart: ChunkStore::remove only updates the
in-memory index, and foyer keeps no tombstone for a removed entry.
A cached header is now used only once this process has confirmed its
object against the backend, so the first read of each object after a
restart costs one HeadObject. Every node-mode fill records the version
it filled, and a chunk is served only under the ETag the read
resolved: locally, from a peer, and by a holder's one-sided write into
client memory, whose response now carries the holder's witness. A
mismatched local copy is forgotten so its re-fill can land; a
mismatched peer copy is skipped and its holder sent an Invalidate.
ETags are compared without quotes, because the scatter path tags
chunks with CompleteMultipartUpload's quoted one.
tests/daemon/restart.rs restarts a daemon over its own cache directory
on both tiers: an overwrite while down, an invalidation before the
restart, and an unchanged object, which must still be served from the
recovered tier after one HeadObject and no re-fill.
Testing
pacer-daemon,pacer-transportandpacer-cachetest suites all pass. The new restart tests fail onmainand pass here, on both disk tiers.-D warnings, including--features efa, is clean on Rust 1.96 and 1.99.Fixes #64
🤖 Generated with Claude Code