Repository navigation
feat(net): pace a moq-transport FETCH run once a reader lost a group to eviction - #8117
Conversation
Quest-Claim: 631390826512d3b7
…to eviction A relay filling a run of groups with one FETCH wrote the whole run at the stream's speed, so on a cache smaller than the run a slow reader lost most of it. Once a reader of the track lost a group it judged cached, the run now holds its fetch stream unread at each group boundary until a reader picked up the group before, through the session's pause budget, so flow control holds the publisher back. The quest is rewritten to the lite-07 remainder, which needs a maintainer decision on its mechanism. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: 872e887
Base: ce0a4f0
No actionable findings in the reviewed changes. The FETCH loop retains the already-decoded next object across a pending pace gate, finishes the previous group before waiting, and resumes through the existing receive-credit pause budget and reset watcher. The eviction evidence selects the existing fill pickup gate without adding a wait to uneventful runs. The regression covers a run larger than the cache with and without prior eviction evidence and opens its receive stream through the session so the pause budget is exercised.
The moq-transport-only scope is clear. Lite-07 history and pacing across multiple fills remain explicitly tracked rather than being represented as solved; the proposed mechanism still needs the maintainer's decision.
Verification: GitHub-only static inspection of the changed FETCH state machine, RangeWriter lifecycle, fill pacing, Reader::poll_pace, test transport and regression. No Cargo builds, tests, interop runs or runtime reproduction. Check run 42331635546 was in progress when inspected; the PR's reported validation was not independently reproduced.
(Written by review (OpenAI))
|
No actionable comments were generated in the recent review. WalkthroughThe change adds eviction-aware pacing at group boundaries in multi-group FETCH runs. When pacing is pending, the FETCH reader retains the next object for a later poll. A new test compares paced and unpaced reads with a slow reader and a limited cache. The test transport can now configure a receive window. Quest documentation now describes lite-07 history delivery paths and pacing approaches. Merge Risk:
|
There was a problem hiding this comment.
ℹ️ No critical issues — one minor suggestion inline.
Reviewed changes
- Pacing gate —
Fill::poll_run_pacedis ready until the track's eviction count is nonzero, then waits asFill::poll_paceddoes. - FETCH run —
GroupFetchObjectsfinishes each group, then holds the stream unread on the gate, stashing the next group's first object inpaced. - Pause budget —
Reader::poll_paceis nowpub(crate)and used for the run gate. - Test transport —
ScriptedSession::with_receive_window, andGroupFetchRunopens through the subscriber's transport. - Quest — rewritten to the lite-07 remainder, with the epic README link retitled.
deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oups/run-fill-pacing
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Follow-up on 17b6c4d since 872e887, accounting for base 75c0847. No new actionable findings.
The substantive update extends the existing regression to a descending subscriber using poll_recv_group, while retaining ordered ascending coverage. Both modes require every group with pacing and demonstrate loss without eviction-triggered pacing. This is focused coverage of the disputed reader mode; the PR's production changes remain unchanged relative to the base. The explicitly deferred lite-07 and multiple-fill work remains outside this test's claim.
Verification: GitHub-only comparison and static inspection of the changed test and its harness. No Cargo tests, interop execution, or quest context run; the reported passing results were not independently reproduced.
(Written by review (OpenAI))
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Descending reader case —
a_fetch_run_waits_for_its_reader_once_one_lost_a_groupnow runs bothOrder::Ascending(viaordered()) andOrder::Descending(viapoll_recv_group), asserting the paced run hands a slow reader all 40 groups and the unpaced run does not. The fill follows the subscription order, so the descending case exercises the descending fill's cursor; the test passes locally.
deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏
Remove the group-boundary pacing #8117 added: once a reader lost a group to eviction, the FETCH stream was held unread until a reader took the group before. Pacing between groups is head-of-line blocking, so a slow reader now falls back on Evicted and refill-once or a refresh, as on lite-07. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Works on quest/m2/unbounded-groups/run-fill-pacing.md: lands the moq-transport half and rewrites the quest to the lite-07 remainder. Follow-up from moq-dev/moq#8017.
Problem
A relay filling a run of groups with one moq-transport FETCH wrote the whole run at the fetch stream's speed. On a cache smaller than the run, the run evicted its own groups before a slow reader took them. Reproduced with a 40-group run on a 4-group pool and a reader taking one group per stream poll: the reader got only groups 36 to 39.
Approach
model/track/fill.rs).Fill::poll_run_pacedis ready at once until the track's eviction count (TrackState::evictions, bumped when a reader loses a group it judged cached) is nonzero, then waits asFill::poll_paced(feat(net)!: pace a batch fill's handler by its fastest reader #8017) does: until a reader picked up every group the fill accepted. An unpaced run still moves at the source's speed while readers keep up.ietf/subscriber.rs,GroupFetchObjects). At each group boundary the run finishes the group before, then holds the fetch stream unread on that gate, keeping the next group's first object until it may open the group. Flow control then holds the publisher back.coding/reader.rs). The hold goes throughReader::poll_pace, nowpub(crate), like within-group pacing: it reserves the stream's receive credit from the session's pause budget, watches for a reset while paused, and reads on unpaced once the budget is full.ScriptedSession::with_receive_window, andGroupFetchRunopens its stream through the subscriber's transport so it pauses like a session's stream.Requiredentry follows.Impact
Alternatives
These were prototyped for lite-07 range fills and dropped. The rewritten quest records them:
FillServeRun): 26 of 40, but it costs a round trip per group, which feat(net)!: pace a batch fill's handler by its fastest reader #8017 and moq-dev/moq#7339 rejected. It also leaves the subscription's own history range unpaced.Choices made without asking
## Waiting.Validation
a_fetch_run_waits_for_its_reader_once_one_lost_a_group(new): with evidence, a slow reader of a 40-group FETCH run on a 4-group pool gets every group, with the stream paused through a session that grants one group of credit. It covers an ordered ascending reader and a descendingpoll_recv_groupreader. Without evidence the same run outruns both: the descending one reads only[39, 38]. With the gate disabled, the ascending paced half reads only[36, 37, 38, 39].just cion872e887f3a: passes (11021 Rust tests).just checkon17b6c4d0f9(after mergingmain): passes.Follow-ups
RangeFills, andRecovery), and feat(net)!: pace a batch fill's handler by its fastest reader #8017's per-fill pacing lets several fills of one reader outrun it together.Review
Codex (
quest review), gpt-6.1-sol, medium effort.872e887f3ab5ce4a66a64646258c3cf5fe0bc743: no findings.17b6c4d0f9544912448ff7d87638a6871052c114: no findings.Online: pullfrog's thread said a descending reader is not held back. Declined with evidence in the reply: the descending case is now in the test and passes. Gating on hand-out instead deadlocks
a_fill_against_its_readers_order_still_finishes.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code