Skip to content

feat(net)!: leave subscriptions and fetches to flow control - #6467

Merged
kixelated merged 14 commits into
mainfrom
quest/m1/api-audit/session-limits
Oct 24, 2026
Merged

kixelated merged 14 commits into
mainfrom
quest/m1/api-audit/session-limits

Conversation

@kixelated

@kixelated kixelated commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Quest: Session limits only where needed

Summary

moq_net::session::Limits drops the subscriptions and fetches caps, which only refused at runtime what flow control already bounds, and gains requests for the one bound they also fed: the drafts 14 to 16 request window. The documented example now compiles (it is a doctest).

Proof that each removed cap is covered, per version:

Cap moq-lite (all) moq-transport 14 to 16 moq-transport 17+
inbound SUBSCRIBE / TRACK / TRACKS one bidi stream each: QUIC stream credit request window (MAX_REQUEST_ID, live <= window) one bidi stream each: stream credit
inbound FETCH one bidi stream each request window one bidi stream each
PUBLISHes we hold for a peer's SUBSCRIBE_TRACKS listing n/a n/a (no SUBSCRIBE_TRACKS) not covered: kept, now bounded by requests (tracks past it are skipped as before)

Stream credit holds because every transport we accept on returns bidi credit only once both halves of a stream close: moq-quic (QUIC, WebTransport), Rust qmux (moq-quic's state machine), and iroh. A peer past it waits; it is not refused.

What stays:

  • announces: lite announces share one stream and IETF namespaces have no other bound.
  • requests: with announces it sizes the drafts 14 to 16 window (2 * (announces + requests)), the draft 17+ skipped-ID history, and the listing PUBLISH bound above. Defaults keep the window where it was: 100,000 + 20,000 in moq-net and on relay peers.
  • The subscriptions_peak stat. Subscriptions are still counted (uncapped) so the peak keeps reporting. On moq-lite it now counts SUBSCRIBE streams only, rather than TRACK, SUBSCRIBE, and TRACKS streams deduplicated per track; that per-track Interests map existed only for the cap and is deleted.

Test: request_caps::flow_control_bounds_the_subscriptions_a_peer_holds asks for 24 subscriptions against a window of 8 and 8 bidi streams, on drafts 14, 15, 16, 17 and lite-06, and checks the server holds at most 8 while the session stays open. It fails (24 held) with both bounds lifted. To express bidi credit, transport::memory::Config gains max_concurrent_bi_streams, mirroring max_concurrent_uni_streams; a bidi stream holds credit until the peer is done with both halves.

Deleted tests that only exercised the removed caps: fetch_caps.rs, held_tracks_share_the_cap_with_their_subscriptions, the lite and IETF "past the cap closes the session" unit tests, coalesced_fetches_each_hold_their_own_slot, and the Interests unit test.

Also aligned IETF join after finish, whose recommendation charged finished entries to the removed subscription limit.

Dropped: the JS mirror. @moq/net keeps its internal subscription and FETCH caps, because @moq/qmux returns MAX_STREAMS credit on accept rather than on close, so stream credit does not bound open streams there. Its comments now say so.

Public API and wire impact

  • moq_net::session::Limits: subscriptions and fetches removed, requests added (unreleased type; the MIGRATE.md entry for feat(net)!: bound peer-declared lengths and per-session requests #4820 is rewritten).
  • moq_net::transport::memory::Config::max_concurrent_bi_streams added (non-exhaustive struct).
  • moq-relay config: [session]/[peer] subscriptions and fetches (--session-subscriptions, --session-fetches, --peer-subscriptions, --peer-fetches, and their env vars) replaced by requests (--session-requests, --peer-requests, MOQ_SESSION_REQUESTS, MOQ_PEER_REQUESTS). Unreleased; old keys fail loud via deny_unknown_fields.
  • Behavior: a peer past what the old caps admitted now waits on flow control instead of losing the session with TOO_MANY_REQUESTS. Relay clients on moq-lite or draft 17+ may hold up to [quic] max_streams (10,000 by default) subscriptions instead of 1,000.
  • Wire: none.

Decisions

  1. Remaining field name: requests, since the relay needs a lower bound for untrusted draft 14 to 16 clients than for peers. Rejected: window (it also bounds listing PUBLISHes and ID history) and no field with a fixed window.
  2. Relay [session] requests default: 10,000 (window 22,000), not 11,000 to keep the old 24,000 exactly.
  3. Listing PUBLISH bound: kept with requests in this PR, since nothing else bounds the PUBLISH tasks a draft 17+ peer's listings spawn. Rejected for now: opening each PUBLISH only as the peer's stream credit admits.

Checks

  • just check: pass (lint and tests for the changed packages, including cargo test -p moq-net).
  • just test interop --all: pass.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 2 commits October 22, 2026 20:56
`session::Limits` drops `subscriptions` and `fetches`: every moq-lite
request and every draft 17+ moq-transport request holds a stream, so
stream credit bounds them, and on drafts 14 to 16 the request window
does. `requests` replaces them where they still fed a bound: the window,
the draft 17+ skipped-ID history, and the PUBLISHes a peer's listings
hold. The relay config follows, and the memory transport gains bidi
stream credit so a test can prove the peer stays bounded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title Session limits only where needed feat(net)!: leave subscriptions and fetches to flow control Oct 23, 2026
kixelated and others added 3 commits October 22, 2026 22:36
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>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Implementation is complete and local checks pass; this stays a draft for the three decisions in the description (field name requests, the relay [session] requests default, and keeping the listing PUBLISH bound).

Suggested follow-ups:

  • @moq/qmux returns MAX_STREAMS credit on accept rather than on close, so stream credit does not bound open streams there. Fixing that would let @moq/net drop its subscription and FETCH caps to mirror Rust.
  • Bound draft 17+ listing PUBLISHes by design (open each only as the peer's stream credit admits) instead of by Limits::requests.

(Written by Claude Opus 5.5)

kixelated and others added 2 commits October 22, 2026 23:58
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 October 23, 2026 08:03
@coderabbitai

coderabbitai Bot commented Oct 23, 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 19 seconds.

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: e05ec39b-1e9c-4e61-951c-06526ef1055c
📥 Commits

Reviewing files that changed from the base of the PR and between 905e1ce and 92423bf.

📒 Files selected for processing: 33
  • doc/bin/relay/config.md
  • doc/concept/stats.md
  • doc/lib/rs/moq-net.md
  • js/net/src/ietf/setup_options.ts
  • js/net/src/util/limits.ts
  • quest/m1/api-audit/README.md
  • quest/m1/api-audit/session-limits.md
  • quest/m1/js-qmux-credit.md
  • quest/m1/listing-credit.md
  • quest/m2/ietf-join-after-finish.md
  • rs/moq-net/MIGRATE.md
  • rs/moq-net/src/auth.rs
  • rs/moq-net/src/client.rs
  • rs/moq-net/src/error.rs
  • rs/moq-net/src/ietf/control.rs
  • rs/moq-net/src/ietf/publisher.rs
  • rs/moq-net/src/ietf/publisher/tracks.rs
  • rs/moq-net/src/ietf/session.rs
  • rs/moq-net/src/lite/publisher.rs
  • rs/moq-net/src/lite/session.rs
  • rs/moq-net/src/server.rs
  • rs/moq-net/src/session.rs
  • rs/moq-net/src/stats.rs
  • rs/moq-net/src/transport/memory.rs
  • rs/moq-net/tests/integration/fetch_caps.rs
  • rs/moq-net/tests/integration/main.rs
  • rs/moq-net/tests/integration/request_caps.rs
  • rs/moq-net/tests/integration/track_stream_demand.rs
  • rs/moq-relay/src/cluster.rs
  • rs/moq-relay/src/config.rs
  • rs/moq-relay/src/limits.rs
  • rs/moq-relay/src/settings.rs
  • rs/moq-tokio/src/client.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 23, 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-24T02:07:51.991435Z 92423bf New commits
ℹ️ 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

@codex review

(Written by Claude Opus 5.5)

@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: d1f2e287ff

ℹ️ 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 thread rs/moq-relay/src/settings.rs
Comment thread rs/moq-relay/src/limits.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated added this pull request to the merge queue Oct 23, 2026

@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: bca38c781b

ℹ️ 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 thread rs/moq-net/src/session.rs Outdated
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 23, 2026

@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: 33a39aaddd

ℹ️ 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 thread rs/moq-net/src/ietf/publisher.rs Outdated
…ered

A peer that cancels a SUBSCRIBE whose token the application already took
now keeps the request stream (and so its stream credit or request window
slot) until the application answers or drops the token. Without this, a
peer could cancel and resubscribe to pile up verifications beyond its
credit, which the removed subscription cap used to bound.

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

Copy link
Copy Markdown
Collaborator Author

@codex review

(Written by Claude Opus 5.5)

@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: ec60f3d088

ℹ️ 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 thread rs/moq-net/src/ietf/publisher.rs Outdated
kixelated and others added 3 commits October 23, 2026 18:15
# Conflicts:
#	rs/moq-net/src/ietf/publisher.rs
#	rs/moq-net/src/lite/publisher.rs
The earlier fix only covered the initial token. A peer could also cancel
after the application took a REQUEST_UPDATE renewal, freeing the
request's credit while the verification stayed in flight. The
subscription's auth hold now carries a kio consumer, and the request
stream closes, after PUBLISH_DONE, only once every token verification
holding it has been answered or dropped. Demand is still released at
once. This replaces the withdraw/poll_released verdict API.

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

Copy link
Copy Markdown
Collaborator Author

Merge pass summary (head 92423bf):

  • Merged main three times. The conflicts were in rs/moq-relay/src/config.rs (main's test_env::Env isolation now applies to the requests limit vars) and in cap tests main had edited that this PR deletes. The new test was adapted to driver::Transport.
  • Docs (Codex P2): session::Limits, SessionError::TooManyRequests, and Error::TooManyRequests now name only the actual close cases: announcement overflow, and the drafts 14-16 request window or MAX_REQUEST_ID.
  • Quests: quest/m1/listing-credit.md and quest/m1/js-qmux-credit.md no longer link the finished session-limits quest. The Required entry on it was dropped, so listing-credit is now unblocked.
  • Auth credit (Codex P2 and P1): with the subscription cap gone, a peer could cancel a SUBSCRIBE after the application took its token, or a renewal's, and so pile up verifications beyond its credit. The subscription's auth Hold now carries a kio consumer, and the request stream closes only once every taken token has been answered or dropped. PUBLISH_DONE is still written at once, and track demand is still released at the cancel. Internal only; no public API or wire change.

Checks: just check and just test interop --all pass on the final tree. One earlier interop run had cpp-publisher audio timestamp-gap failures that did not reproduce on rerun.

(Written by Claude Opus 5.5)

@kixelated
kixelated added this pull request to the merge queue Oct 24, 2026
Merged via the queue into main with commit 164c1ad Oct 24, 2026
10 checks passed
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