Skip to content

feat(net): a cold moq-transport copy resolves relative anchors from its live join - #7283

Merged
moq-bot[bot] merged 6 commits into
mainfrom
quest/m1/subscribe-ranges/lite
Oct 31, 2026
Merged

moq-bot[bot] merged 6 commits into
mainfrom
quest/m1/subscribe-ranges/lite

Conversation

@kixelated

@kixelated kixelated commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

A Rust moq-transport copy refused a Relative(n) anchor whenever its cache couldn't settle it yet, e.g. a cold relay copy asked for Relative(2)... The maintainer's 2026-10-27 decision says a bridge never sends a relative anchor upstream. Instead it resolves the anchor to an absolute Group ID from its cache or from the live edge before sending, and a cold copy should do that from a live join's Largest Object rather than refuse.

Approach

  • IETF subscriber (rs/moq-net/src/ietf/subscriber.rs): when the aggregate's ranges can't be resolved yet and carry no time anchor, the SUBSCRIBE goes out as the live join instead of being refused. After SUBSCRIBE_OK, the anchor resolves against the answer's Largest. This happens before register_alias lets any data stream in, so a newer group that lands first can't shift it. The resolved bounds go upstream as an ordinary absolute update. If the answer has no Largest, or a later demand change is still unresolved, the loop waits for the next group (settle_bounds) instead of aborting the copy.
  • Model (rs/moq-net/src/model/track.rs): new Producer::report_edge. It records a live join's answered Largest as Feed::Live.edge (and first if not yet set), so the copy's readers count relative starts back from it. refuse_cached_anchors now refuses only an unresolved time anchor; a relative one waits for the live edge, as on lite-07.
  • Time anchors the cache can't settle are still refused, since a live join's answer doesn't place a presentation time.
  • The per-wire table in rs/moq-net/tests/integration/range_anchors.rs now expects moq-transport-18 and -22 to read every relative case (open and bounded) as the held track does. They are compared sorted because the backfill below the live group arrives after it. Ordered reads belong to read-backfill.
  • Docs: doc/concept/moq-lite.md and track::Anchor describe the new behavior.
  • Quest: quest/m1/subscribe-ranges/lite.md is rewritten to the work that remains, the lite-07 range fill through the subscription. Links in lite07-finalize.md and the epic README are updated.

Choices made without asking:

  • The open-ended relative case also sends the resolved absolute start as an update, as a warm copy's resolution already does, rather than staying on the plain live join. The groups below the live edge still arrive through the copy's fills.
  • report_edge applies to every live join with a Largest, not only deferred ones, so the copy's readers and the upstream resolve from the same edge.

Impact

  • Public API: none (report_edge is crate-private).
  • Wire: unchanged for every version. moq-transport now sends a SUBSCRIBE_UPDATE / REQUEST_UPDATE carrying absolute bounds in cases that used to be refused.
  • Behavior: a reader of a moq-transport copy that asks for Relative(n) (n ≥ 1) or a relative end now gets data instead of Unsupported.

Validation

At 809095c:

  • quest gate just ci origin/main: passes (9050 Rust tests and the JS suites).
  • quest gate just test interop --all: all checks pass (run at 431e0e2, before the follow-up fix, which touches only IETF copy resolution).
  • New unit test model::track::test::a_relative_start_counts_from_the_answered_edge: fails without report_edge (Unsupported) and passes with it.
  • quest check --base origin/main: 669 documents OK.

Decisions

  1. Land this slice, or keep going on this PR? The quest's main item, the lite-07 range fill through the subscription, is not here. It overlaps the fill-path work in moq-dev/moq#7215.
    • ✅ (a) Merge this PR as it is. Maintainer decision, 2026-10-30. The quest file already describes only the range fill, and the next /quest-start takes it from there.
    • (b) Keep this PR open and add the range fill here, which makes it one large PR.

Review

  • Reviewer: Codex, gpt-6.1-sol, medium effort (quest review --base origin/main, quest pinned at 01d051cf5d).
  • Round 1 at f05cbbd: one finding. A deferred anchor resolved from the first arriving group rather than the answer's Largest Object. Fixed in 809095c with report_edge, resolution before the alias is bound, and a regression test.
  • Round 2 at 809095c: no findings.

Follow-ups

  • draft-18: the first SUBSCRIBE refuses a bounded end (subscribe_join), but an update on the same wire carries an absolute end. That predates this PR, but means a warm and a cold copy differ for absolute bounded ranges on draft-18. Worth a /quest-plan look.
  • Time anchors on a cold moq-transport copy are still refused. Resolving them would need the copy to learn group start times first.

Quest: quest/m1/subscribe-ranges/lite.md

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 5 commits October 29, 2026 22:53
…ts live join

A moq-transport copy that cannot settle a relative anchor from its cache
joins live instead of refusing it, and resolves the anchor once the
Largest Object or a newer group names the live edge. The resolved bounds
go upstream as an absolute update. Time anchors the cache cannot settle
stay refused.

Rewrites quest/m1/subscribe-ranges/lite.md to the remaining range fill.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gest

A live join's Largest becomes the copy's live edge, and the deferred
upstream bounds resolve before the alias admits any data stream, so a
newer group landing first cannot move either resolution.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title Lite-07 ranges feat(net): a cold moq-transport copy resolves relative anchors from its live join Oct 30, 2026
@kixelated
kixelated marked this pull request as ready for review October 30, 2026 20:54
@coderabbitai

coderabbitai Bot commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 35 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f75fbbad-f2a4-4f28-a792-04a64a9e05e8
Commits

Reviewing files that changed from the base of the PR and between 1c733a0 and 809095c.

Files selected for processing: 8
  • doc/concept/moq-lite.md
  • quest/m1/lite07-finalize.md
  • quest/m1/subscribe-ranges/README.md
  • quest/m1/subscribe-ranges/lite.md
  • rs/moq-net/src/ietf/subscriber.rs
  • rs/moq-net/src/model/subscription.rs
  • rs/moq-net/src/model/track.rs
  • rs/moq-net/tests/integration/range_anchors.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 30, 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-10-30T20:56:01.236103Z 809095c 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

Copy link
Copy Markdown
Collaborator Author

Landing. Maintainer decision (2026-10-30): merge this slice. The quest keeps the lite-07 range fill. Codex reviewed 809095c150 with no findings, and just ci origin/main passed on it.

(Written by Claude Opus 5.5)

@kixelated
kixelated enabled auto-merge (squash) October 30, 2026 20:54

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 809095c150

ℹ️ 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".

Comment on lines +3387 to +3391
if let Ok(mut state) = self.modify()
&& let Feed::Live { first, edge } = &mut state.feed
{
*edge = (*edge).max(Some(group));
first.get_or_insert(group);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the answered edge when resuming an idle copy

When a returning subscriber requests Relative(2) on an idle moq-transport copy, subscribe_once defers resolution, but this guard discards the answer's Largest because the feed is still Feed::Idle. If Largest names group 4 and group 5 arrives before group 4, the resume loop's set_live calls go_live, which initializes first from the newest produced group, 5. Both the reader and the deferred upstream bounds then resolve the start to 3 instead of 2, silently omitting requested history. Preserve the answered anchor across the idle-to-live transition without making stale cached data readable prematurely. This also violates the warm/cold upstream-state invariant in rs/moq-net/AGENTS.md.

AGENTS.md reference: rs/moq-net/AGENTS.md:L8-L8

Useful? React with 👍 / 👎.

@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 commit: 809095c150568af26c6a2377c188867ca5f210c5.

  • P2, existing independent finding: I confirmed the idle-copy anchor loss at rs/moq-net/src/model/track.rs:3387-3391, already reported here; no duplicate inline comment. report_edge ignores Feed::Idle, and the resume path subsequently calls set_live after a newer group arrives. go_live takes the maximum of that group and the answered edge, so Largest=4 followed first by group 5 makes Relative(2) start at 3 rather than 2. Preserve the answered anchor across resume while retaining the stale-cache readability gate, and cover the idle/resume case.

Direction: resolving to absolute bounds through the existing range resolver is a sensible, contained alternative to introducing another relative wire mapping. The fresh-copy ordering fix is present, but the same invariant needs to cover resumed copies. No additional actionable bugs found in the changed paths.

Verification: static review of the diff, subscription/update flow, model feed transitions, and changed tests. I did not run tests or independently verify the reported CI results.

(Written by OpenAI)

@moq-bot
moq-bot Bot merged commit 654aacb into main Oct 31, 2026
7 checks passed
@moq-bot
moq-bot Bot deleted the quest/m1/subscribe-ranges/lite branch October 31, 2026 05:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant