Repository navigation
feat(net): negotiate IETF subscriber max age - #5993
Conversation
Map negotiated SUBSCRIBE and REQUEST_UPDATE budgets onto existing subscription max delay in Rust and JavaScript. Preserve legacy backlog behavior and newest groups, and relay the most tolerant subscriber budget. Checkpoint: JS max-age regressions and net typecheck pass. Rust integration helper compile fix, draft parsing, full checks, cross-language interop, and shaped acceptance validation remain pending. Co-Authored-By: GPT-6.1-Sol <noreply@openai.com>
Mirror the accepted track aggregate into its metadata query subscription so the original max-delay budget cannot mask a later decrease. Drive the regression reader while updating its preferences, as required by the caller-driven route cursor. Validation: all 49 scoped IETF codec, two-hop max-age aggregation, catalog survival, and partial-group regressions pass. The active-reader regression fails without the query-hold fix. Co-Authored-By: GPT-6.1-Sol <noreply@openai.com>
Validation: full branch check caught the incorrect draft URL; generated site route is /draft/moq-timestamp. Co-Authored-By: GPT-6.1-Sol <noreply@openai.com>
Direct full-subscription fixtures now model a received SETUP without extensions, so capability negotiation can complete. Leave delayed-SETUP and raw receiver fixtures unchanged. Validation: all 2518 moq-net tests pass, including two-hop max-age aggregation and the legacy joining-fetch cases. Co-Authored-By: GPT-6.1-Sol <noreply@openai.com>
Resolve conflicts with MoQ Epoch: SUBSCRIBE carries both parameters, encoded in ascending key order (EPOCH 0x40B69 before MAX_AGE 0x915C6). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou'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 11 minutes. View limit details
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. Comment |
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: 9b506f9259
ℹ️ 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".
Draft-17+ dial and accept destructured the SETUP result field by field and dropped maxAge, so JS subscribers never sent MAX_AGE on ALPN-selected drafts. Spread the whole result so every negotiated flag reaches the connection. An end-to-end JS test now checks SUBSCRIBE and REQUEST_UPDATE budgets reach the publisher on drafts 16, 17, and 22; 17 and 22 fail without the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve conflicts with the dynamic-groups refresh ratio: SUBSCRIBE and REQUEST_UPDATE keep the subscriber max age alongside main's fixed-range bounds and join-judged NEW_GROUP_REQUEST. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Validation: the drill passes at baseline and fails with the mutation applied. 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>
Problem
A moq-transport subscriber cannot bound the age of groups the publisher serves. IETF delivery timeouts also expire the newest group and cannot represent moq-lite's subscription budget.
Closes #5881.
Approach
Negotiate subscriber max age in SETUP, carry the existing max-delay budget on SUBSCRIBE and REQUEST_UPDATE, and apply it through the existing group-expiration policy in Rust and JavaScript. Relays retain the most tolerant subscriber's budget; absence preserves retained backlog, and the newest group survives every budget. Metadata query subscriptions follow the aggregate too, so an initial budget cannot mask a later decrease. Update the Timestamp draft and standard guidance.
Direct subscription fixtures now explicitly declare their peer SETUP. Delayed-SETUP tests and peers without max-age support retain their existing negotiation assertions.
Impact
0x40B69, draft 17+) and MAX_AGE (0x915C6); keys are encoded in ascending order.0x915C4and subscriber parameter0x915C6, in milliseconds, on drafts 14 through 22. Send the parameter only to peers declaring the option.Alternatives
Reusing OBJECT_DELIVERY_TIMEOUT or SUBGROUP_DELIVERY_TIMEOUT would cut newest groups, including quiet catalog snapshots. Sending an unnegotiated parameter would close legacy sessions.
Validation
Validated commit
7116ef3dfe8dce247c2d43e5a0f954e09cac9778:just check: passed, including all 7,535 native tests, additional feature suites, workspace JavaScript tests and type checks, documentation, lint, and target checks.just drafts check: passed.just rs test -p moq-net: all 2,518 tests passed, 8 skipped. The initial broad run exposed two joining-FETCH fixtures that never supplied peer SETUP; explicit fixture declarations fix both without changing production negotiation.just rs test -p moq-net -E 'test(subscriber_max_age) | test(ietf::subscribe::tests) | test(partial_group::)': all 49 tests passed, including most-tolerant aggregation and budget decreases across supported drafts, newest catalog survival, and partial-group resets.just test interop --publishers rust,python,go,cpp --subscribers rust,python,go,cpp,js-native-node,js-native-bun,c,gst --timeout 30: passed all available native matrix, unauthorized-publisher, CLI FETCH, and finite-tail checks.just test drill ietf_subscriber_max_age_skips_bufferbloat: passed. The drill uses a finite 500ms queue below the media bitrate and verifies overflow drops, with random loss disabled.just test drill-sensitivity --no-baseline subscriber-max-age-ignored: passed, 1 of 1. Removing initial publisher max-age application makes the drill fail withsubscriber max age did not reach the publisher. Patch application also passed separately.Iteration (Claude Opus 5.5)
Merged
origin/main(MoQ Epoch, #5836 and neighbors). Conflicts were unions of the two extensions' fields inPeer,PeerSetup,Subscribe, the SETUP parameter enum, and the JS subscriber. The Rust parameter macros require ascending keys, so EPOCH now precedes MAX_AGE in SUBSCRIBE encode and decode. No review findings were posted.Decisions: none needed; the merge adopted main's
PeerSetup::newand kept this PR'sPeerSetup::declaredtest fixture.Validated on the merge commit:
just check: passed.just drafts check: passed.just rs test -p moq-net(nextest, all features): 2,572 passed, 8 skipped.js/nettypecheck andbun test src/ietf: 701 passed.just test interop --all, browser included: all checks passed. This closes the gate the previous iteration left open.Round 2 (Claude Opus 5.5)
Codex finding r4320231271: JS draft-17+ dial and accept dropped
maxAgewhen destructuring the SETUP result, so JS never sent MAX_AGE on ALPN-selected drafts. Both call sites now spread the whole result. A newjs/net/src/integration.test.tscase covers drafts 16, 17, and 22 end to end; 17 and 22 fail without the fix.just checkandjust test interop --allpass on the fix.Merged
origin/mainagain (refresh-ratio dynamic groups): SUBSCRIBE and REQUEST_UPDATE keep the max age alongside main's fixed-range bounds and join-judged NEW_GROUP_REQUEST, and thesubscriber-max-age-ignoreddrill mutation is retargeted (the drill passes at baseline and fails with the mutation).just checkand moq-net and js/net tests pass on the merge;just test interop --allwas rerun on the final head.Follow-ups
None.
🤖 Generated with Claude Code
(Written by GPT-6.1-Sol; iterated by Claude Opus 5.5)