Describe the bug
FoyerLayer can ignore OpRead / OpStat arguments while filling the full-object cache.
In core/layers/foyer/src/full.rs, FullReader::fallback_open and fallback_read correctly call the inner accessor with self.args.clone(). However, read_full_object() fills the cache by calling:
stat(&path_clone, OpStat::default())
read(&path_clone, OpRead::default())
The cache key only includes path and version, derived from self.args.version().
This can make the cache-fill path observe different read conditions than the original reader request.
Steps to Reproduce
- Enable
FoyerLayer.
- Read an object through
reader_with(path) or read_with(path) with read arguments such as version, if_match, if_none_match, or other conditional read options.
- Trigger a full-object cache miss so
read_full_object() fills the cache.
- Observe that the cache-fill path uses default read/stat args instead of the original request args.
Relevant code:
fallback_open uses self.args.clone(): core/layers/foyer/src/full.rs
fallback_read uses self.args.clone(): core/layers/foyer/src/full.rs
- cache-fill uses
OpStat::default() and OpRead::default(): core/layers/foyer/src/full.rs
- cache key only includes
path and version: core/layers/foyer/src/full.rs
Expected Behavior
The cache-fill path should preserve the semantics of the original read request.
At minimum:
stat / read used for cache fill should be derived from self.args.
- Versioned reads should not accidentally fetch latest content and store it under a versioned cache key.
- Conditional reads such as
if_match / if_none_match should either be respected during cache fill or explicitly bypass the cache after validating the condition.
Additional Context
This was found during post-merge review of the read-reader refactor. The new design makes Access::read return a reusable raw reader, so layers need to preserve OpRead semantics across both reader creation and later reader-side IO.
Suggested tests:
FoyerLayer + reader_with(path).version(v) cache miss/hit behavior.
FoyerLayer + read_with(path).if_match(...) cache miss/hit behavior.
- Ensure fallback and cache-fill paths observe the same read arguments.
Are you willing to submit a PR to fix this bug?
Describe the bug
FoyerLayercan ignoreOpRead/OpStatarguments while filling the full-object cache.In
core/layers/foyer/src/full.rs,FullReader::fallback_openandfallback_readcorrectly call the inner accessor withself.args.clone(). However,read_full_object()fills the cache by calling:stat(&path_clone, OpStat::default())read(&path_clone, OpRead::default())The cache key only includes
pathandversion, derived fromself.args.version().This can make the cache-fill path observe different read conditions than the original reader request.
Steps to Reproduce
FoyerLayer.reader_with(path)orread_with(path)with read arguments such asversion,if_match,if_none_match, or other conditional read options.read_full_object()fills the cache.Relevant code:
fallback_openusesself.args.clone():core/layers/foyer/src/full.rsfallback_readusesself.args.clone():core/layers/foyer/src/full.rsOpStat::default()andOpRead::default():core/layers/foyer/src/full.rspathandversion:core/layers/foyer/src/full.rsExpected Behavior
The cache-fill path should preserve the semantics of the original read request.
At minimum:
stat/readused for cache fill should be derived fromself.args.if_match/if_none_matchshould either be respected during cache fill or explicitly bypass the cache after validating the condition.Additional Context
This was found during post-merge review of the read-reader refactor. The new design makes
Access::readreturn a reusable raw reader, so layers need to preserveOpReadsemantics across both reader creation and later reader-side IO.Suggested tests:
FoyerLayer + reader_with(path).version(v)cache miss/hit behavior.FoyerLayer + read_with(path).if_match(...)cache miss/hit behavior.Are you willing to submit a PR to fix this bug?