feat(net): move wall-clock LRU expiry to the cache pool - #3169
Conversation
Track max_age used to drive two different clocks: the media-timestamp staleness budget and the wall-clock idle scan in evict_expired. The wall-clock half now lives on cache::Pool as an expiry window (default 30s, None to disable), so a track can promise a 5s media window while the pool reclaims anything unaccessed for 30s of real time. Media timestamps stand still during a congestion stall, so a short max_age can no longer age content out of the cache mid-stall; the LRU window is purely about not pinning RAM on content nobody reads. The origin's cache_duration keeps only its media-time role: clamping each track's advertised max_age. The relay's cache-duration knob now also sets the pool expiry, which is what its docs already promised (retained since last written or served from cache). Frame-write settlement now runs the expiry scan too, so a track appending frames to open groups without inserting new ones still ages idle siblings out. Progress on #3161 (the Rust reclamation half). Still open there: idle reclamation with zero writes needs a wakeup the model layer deliberately does not own, and the JS retention prune still keys off maxAge and retains open groups. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3afea3d1b8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Preserve the no-eviction contract for bare unbounded pools while explicitly enabling the default idle window for bounded pools, standalone origins, and relays. Run time-based scans for small whole-frame and streamed writes, with regression coverage for both paths. Co-Authored-By: GPT-5 <noreply@openai.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f219573736
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Route both origin and forwarded datagram writes through the cache's throttled settlement path after releasing the track lock. This keeps idle group expiry progressing for active datagram-only publishers. Co-Authored-By: GPT-5 <noreply@openai.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: deacd2f5b6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Keep the shared cache pool on prefetched consumers and query its current refresh cadence. Existing readers now follow expiry changes made after their cursor was created. Co-Authored-By: GPT-5 <noreply@openai.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c3c2135282
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Keep prefetched consumers on the stricter of the current pool expiry cadence and the track retention cadence. Add a regression test for a short track max_age with a longer pool expiry. Co-Authored-By: GPT-5 <noreply@openai.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5ebb30b649
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Clamp pending write-driven scan deadlines against the pool current expiry cadence so existing tracks respond promptly when a shared pool is shortened. Add a regression for the default-to-subsecond transition. Co-Authored-By: GPT-5 <noreply@openai.com>
Keep the rotating scan cursor outside observable track state and inspect each candidate window before taking a notifying write guard. Rename the new expiry configurator to a setter so its shared mutation is explicit.
Make idle expiry immutable pool configuration while preserving dynamic capacity resizing for the relay memory governor.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 482d6fa834
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Summary
track::Info::max_agestays on the media timeline, whilecache::Poolowns idle expiry.cache::Configwhen constructing a pool. Expiry is immutable after construction, while capacity remains resizable for the relay memory governor.Pool::unbounded()keeps its never-evict contract.cache-durationconfigure both the idle LRU window and the media-timestamp retention ceiling.Public API
cache::DEFAULT_EXPIRY.cache::Config, withConfig::with_capacity(...)andConfig::with_expiry(...).Pool::new(...)to acceptcache::Configinstead of a capacity value.Pool::expiry().Pool::resize(...)remains for dynamic capacity changes.dev.Observable behavior
Non-latest groups idle past the configured window are reclaimed with
Error::Oldon a subsequent write. The latest group remains protected, and there is no background reaper. This is observable to network clients fetching or reading cached history, but the wire encoding and protocol framing are unchanged.Test plan
just fix origin/devjust check origin/devjust test default origin/dev(3,467 Rust tests, 52 Python tests, and all JavaScript suites passed)just rs test -p moq-net -p moq-relay -p moq-ffi(1,415 passed)Cross-package sync
js/netmirror because browser clients do not own the relay-side cache pool. The related JavaScript retention design remains tracked in Retention should reclaim idle open groups now that expiry is timestamp-only #3161.(written by GPT-5)