Reshape lifecycle API: Default RequestState threaded by &mut (0.7.0)#124
Merged
Conversation
2d16372 to
e12833e
Compare
This was referenced Jun 24, 2026
fsdvh
reviewed
Jun 24, 2026
fsdvh
reviewed
Jun 24, 2026
BREAKING (0.7.0). Collapses the growing per-operation variant cross-product. - `Lifecycle::RequestState` now requires `Default`; `begin_request` and `end_request` are removed. State is built via `Default` and finalized by its own `Drop` (which releases evicted items outside the shard lock). - The `*_with_lifecycle` methods now take `&mut L::RequestState` (returning `()` / `Result<(), _>`) instead of returning the state, so one state can be threaded through several ops to batch eviction work or inspect evicted items. This supersedes the `_with_state` proposal in #122. - Drops the now-vestigial `&L` plumbing from the placeholder machinery and the unused `Cache::lifecycle` field; shards keep their own clones for the hooks.
set_capacity created and dropped its own RequestState inside the shard method, so when called via Cache::set_capacity (shard.write().set_capacity) the evicted items were released while the write lock was still held — contradicting the documented Drop-after-lock contract. Take &mut lcs from the caller instead, so it drops after the lock guard. Also use Default::default() consistently instead of L::RequestState::default().
2c74856 to
dbfcea7
Compare
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.
Summary
Reshapes the
LifecycleAPI so that operations needing lifecycle control have a single explicit form instead of a growing cross-product of per-operation variants (_with_lifecyclereturning state,_with_statetaking&mut, …).This is a breaking change →
0.7.0. It supersedes the_with_stateapproach in #122.What changed
Lifecycle::RequestState: Default— the request state is now constructed viaDefaultand finalized by its ownDrop. Thebegin_requestandend_requesttrait methods are removed: every in-tree impl'sbegin_requestwas justDefault::default(), and all lifecycle access already happens through&selfin the eviction hooks, so neither method earned its place. Correctness (releasing evicted items outside the shard lock) now lives entirely inDrop for RequestState.*_with_lifecyclemethods take&mut L::RequestState(returning()/Result<(), _>) instead of returning the state. The&mutform is a strict superset of the old returning form — you own the state, so you can inspect evicted items and decide when to drop it — and it additionally lets you thread one state through several operations to batch the eviction work:Applied uniformly across
insert/try_insert/replaceand the placeholder-guard inserts, on bothsyncandunsync. The ergonomic one-shots (insert,try_insert,replace) are unchanged.Cleanup: removed the now-vestigial
&Lparameter threaded through the placeholder machinery (it existed only to feedend_request) and the unusedCache::lifecyclefield — shards keep their own clones for the hooks.Migration
Custom
Lifecycleimpls: drop yourbegin_request/end_request(move anyend_requestwork intoDrop for RequestState) and ensureRequestState: Default.Note / footgun
The default
RequestStateis[Option<_>; 2]— best-effort space for ~2 evictions. Threading one state through a large batch of inserts means evictions beyond the first two are dropped inside the shard lock. Callers who batch heavily should use aVec-backed lifecycle. (Pre-existing behavior, but batching is now a blessed pattern, so worth calling out.)Verification
cargo build --all-targets,cargo test(57 passed),cargo doc,cargo clippy— clean (one unrelated pre-existing bench warning).RUSTFLAGS="--cfg fuzzing" cargo checkinfuzz/— clean; the fuzz targets exercise the new&mutinspect-evicted path.