Skip to content

fix(ietf): skip FETCH holes to the next cached group when nothing is upstream - #4558

Merged
kixelated merged 7 commits into
quest/m1/moxygen/READMEfrom
quest/m1/moxygen/fetch-span
Sep 30, 2026
Merged

kixelated merged 7 commits into
quest/m1/moxygen/READMEfrom
quest/m1/moxygen/fetch-span

Conversation

@kixelated

@kixelated kixelated commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

The standalone FETCH walk (walk_fetch in rs/moq-net/src/ietf/publisher.rs) asked fetch_group for every sequence from the start of the range to the newest group. With no fetch handler, each miss resolves at once, so one FETCH over a sparse track (for example groups 0 and 2^40) ran 2^40 iterations without yielding. With a handler, a relay sends one upstream FETCH per missing sequence.

Approach

This lands only the no-handler half of quest/m1/moxygen/fetch-span.md plus its benchmark, as the maintainer decided, and deletes that quest: its relay (handler) half moves to the new quest/m1/subscribe-ranges/ line planned in #4565.

  • With nothing upstream to ask, the cache is the whole track. A hole now jumps straight to the next cached group, capped at the newest group so that group's own probe still decides where the track ends.
  • New crate-private track::Consumer::next_cached and fetches_misses. A spliced track looks for the next cached group across every segment and checks its newest segment for a handler, since that is where fetches go.
  • With a handler, each missing sequence is still asked upstream one at a time. FETCH is authoritative, so a local hole cannot be answered as absent. Bounding that cost is the relay half, which moves to quest/m1/subscribe-ranges/ (quest: subscribe ranges replace FETCH in lite-07 #4565).
  • Regression test a_standalone_fetch_skips_a_sparse_span fetches across groups {0, 5, 2^40}. Without the fix it hits nextest's TIMEOUT.
  • New bench fetch (cargo bench -p moq-net --features fuzz --bench fetch) sweeps range span and present-group count as separate axes, reaching the private walk through the hidden fuzz module as the announce bench does. Local results with 64 groups: fetch/span stays flat at about 100-150 µs from 2^6 to 2^40. fetch/present over a 2^24 range grows about linearly, from 4.6 µs for 1 group to 16.6 ms for 4096 groups (noisy machine).

Impact

  • Public API: none. The new track::Consumer helpers are pub(crate), and moq_net::fuzz::walk_fetch is behind the hidden, off-by-default fuzz feature.
  • Wire: none. FETCH_OK and the objects sent are unchanged for every range; only the number of fetch_group probes on holes changes.

Alternatives

Considered for the handler case, which now moves to quest/m1/subscribe-ranges/ (#4565):

  1. Range fill in the model (recommended). The walk issues one upstream request per run of local misses, so upstream requests are at most the cached-group count plus one. The IETF handler answers it with one standalone FETCH and caches every group that comes back. This is how moxygen's MoQCache fills cache gaps (fetchImpl / fetchUpstream, one interval per gap). It needs a range request on track::Dynamic or group::Request (additive public API) and a receive path for multi-group fetch streams in ietf/subscriber.rs, which should land after quest/m1/moxygen/fetch-fill.md. moq-lite FETCH names a single group, so a lite upstream would keep probing one sequence at a time.
  2. Option 1 plus a moq-lite FETCH range in the next lite draft version, so a lite upstream is bounded too. This is a wire and draft change.
  3. Cap the upstream probes per FETCH and end the response early, with FETCH_OK's End Location at the last position probed. No API change, but the cap is arbitrary, and a peer has to send many FETCHes to cross a wide sparse range.

Follow-ups

  • The relay half moves to quest/m1/subscribe-ranges/ (quest: subscribe ranges replace FETCH in lite-07 #4565). This PR deletes fetch-span.md and its entry in the moxygen README.
  • Optionally, cache known-absent ranges from an upstream FETCH (moxygen does) so repeated FETCHes do not go upstream again for the same holes.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

kixelated and others added 3 commits September 29, 2026 13:30
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…upstream

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review September 29, 2026 23:37
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-29T23:40:29.653732Z 82cc24a Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed head: 82cc24a

Direction: a good, narrowly scoped optimization. A publisher with no miss handler can safely treat its cache as authoritative and jump to the next cached group. Keeping the handler-backed walk unchanged is preferable to silently declaring upstream holes absent. The relay-side range-fill design is a separate, larger change and should stay separate.

No additional actionable defect found in the changed walk, plain/spliced cache helpers, regression test, and benchmark. checked_add preserves termination at the maximum sequence, and the latest-group cap retains the terminal probe. The sparse-span test covers the original denial-of-service shape; splice coverage would be a useful extension.

Verification: static diff and surrounding-source review only; Rust/Nix/just tooling is unavailable here, so I did not execute the tests or benchmark.

(Written by OpenAI)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

…p-4558

# Conflicts:
#	quest/m1/moxygen/README.md
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@kixelated
kixelated merged commit 7b51ce5 into quest/m1/moxygen/README Sep 30, 2026
10 checks passed
@kixelated
kixelated deleted the quest/m1/moxygen/fetch-span branch September 30, 2026 03:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant