Skip to content

feat(relay): configure client and peer request caps - #5310

Merged
kixelated merged 7 commits into
mainfrom
quest/m1/relay-session-limits
Oct 13, 2026
Merged

kixelated merged 7 commits into
mainfrom
quest/m1/relay-session-limits

Conversation

@kixelated

@kixelated kixelated commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Every relay session inherits moq-net's request caps (100,000 announcements, 10,000 subscriptions), sized for cluster links, so an ordinary viewer or publisher gets a mesh-sized allowance. Operators cannot configure the client and peer policies separately, and C/UniFFI clients classify a request-cap closure as an unknown error.

Approach

Add [session] and [peer] tables with announces and subscriptions, mirrored by --session-* / --peer-* flags and MOQ_SESSION_* / MOQ_PEER_* env vars. The relay picks the policy after admission and before answering SETUP on the native, WebSocket, and io_uring paths. Only an admitted peer grant selects peer caps (upstream requires peer, and verified LAN membership mints a peer grant); a client certificate, route hop, or cluster-looking path alone does not. Outgoing cluster links use the peer policy.

Append a structured TooManyRequests protocol kind across C, UniFFI, the wrappers, and OBS. OBS explains a request-cap closure instead of reporting a generic connection failure.

These caps are not arbitrary runtime limits: they are moq-net's existing session::Limits, now operator-configurable per role with sane defaults, and exceeding one already closed the session with TOO_MANY_REQUESTS. The PR only lets operators size them and gives clients a smaller default.

Decisions

Settled during /quest-iterate (the maintainer accepted the recommended picks):

  • Table names:
    1. [session] and [peer], leaving one peer table for the QUIC peer limits. ✅
    2. [client] for ordinary sessions; overlaps the relay's outbound client terminology.
  • Ordinary default:
    1. 1,000 announcements and 1,000 subscriptions per client session. ✅ Comfortably above one viewer or publisher, two orders below a mesh link.
    2. Tighter (100 or fewer).
    3. Keep moq-net's mesh-sized defaults until configured.
  • Builder name: with_limits on moq_net::server::Request, moq_tokio::server::Request, and moq_tokio::Client, matching moq_net::Server::with_limits and the other with_* builders. ✅
  • Peer selection keys on grant.peer alone, since grant validation already refuses upstream without peer. ✅

Impact

  • moq-relay: new limits::{Session, Peer} module; Config.session / Config.peer; cluster::Options.session / cluster::Options.peer; flags --session-announces, --session-subscriptions, --peer-announces, --peer-subscriptions and matching env vars and TOML keys. Behavior: ordinary sessions now default to 1,000 / 1,000 instead of 100,000 / 10,000; peers keep 100,000 / 10,000.
  • moq-net: server::Request::with_limits.
  • moq-tokio: server::Request::with_limits, Client::with_limits.
  • moq-ffi: MoqProtocolKind::TooManyRequests appended as the last variant.
  • moq-c: MOQ_PROTOCOL_KIND_TOO_MANY_REQUESTS = 25; existing values unchanged.
  • Go: ProtocolKindTooManyRequests. Dart, Kotlin, Swift, Python, and C++ pick it up through their generated ProtocolKind.
  • OBS: a request-cap closure has its own failure code and dock message.
  • Wire: none. TOO_MANY_REQUESTS stays session code 7. On moq-transport drafts 14 to 16 the caps also size the request window, so very small values can stall other requests.

Composition with JS (#5214): the browser enforces moq-net's 100,000 / 10,000 on what the relay holds on it, while the relay enforces these caps on what the browser holds on the relay. They bound opposite directions, and @moq/net already names code 7 SessionCode.TooManyRequests.

Validation

  • Merged with main; just check passes on the head.
  • just test interop --all passes, including the browser refused session check; all four flags appear in the built relay's --help.
  • C and UniFFI error-kind regressions; config precedence and peer classification unit tests; real TCP and WebSocket tests prove the ordinary cap closes the session and a peer grant keeps its allowance.
  • Interop on the original head failed refused session with Connection lost. The relay log shows that session refused at admission ("the auth server refused the session"), before the request-cap code runs, so it is the known flake tracked in quest/m1/test-flakes-2/interop-close-code.md, not this change. This PR records that run and its relay-log evidence in that quest. It passes locally and in CI on the rebased head.

Alternatives

See Decisions.

Follow-ups

  • The peer-limit quest (quest/m1/quic/peer-limits.md) extends [peer] with the QUIC stream and window values; its reference is updated and this PR completes the relay session limits quest.
  • Swift/macOS validation runs in its platform workflow.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 4 commits October 12, 2026 19:53
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
…y grant

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated force-pushed the quest/m1/relay-session-limits branch from 6d7abcf to 8d7c53c Compare October 13, 2026 02:53
@kixelated
kixelated marked this pull request as ready for review October 13, 2026 02:53
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 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-13T02:57:12.979258Z 8d7c53c 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.

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

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 1 minute.

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
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: eddc57af-7902-4348-85a5-fb487dd543c5
📥 Commits

Reviewing files that changed from the base of the PR and between 522b282 and fff7250.

📒 Files selected for processing (37)
  • cpp/obs/src/moq-dock.cpp
  • cpp/obs/src/moq-error.h
  • cpp/obs/src/moq-output.cpp
  • cpp/obs/test/moq-error-test.cpp
  • dart/moq_ffi/lib/src/moq.dart
  • doc/bin/obs.md
  • doc/bin/relay/config.md
  • doc/concept/stats.md
  • doc/lib/c/index.md
  • doc/lib/cpp/index.md
  • doc/lib/dart/index.md
  • doc/lib/go/index.md
  • doc/lib/kt/index.md
  • doc/lib/py/index.md
  • doc/lib/swift/index.md
  • go/wrapper/errors_test.go
  • go/wrapper/types.go
  • py/moq-rs/tests/test_local.py
  • quest/m1/README.md
  • quest/m1/quic/peer-limits.md
  • quest/m1/relay-session-limits.md
  • quest/m1/test-flakes-2/interop-close-code.md
  • rs/moq-c/src/error.rs
  • rs/moq-ffi/src/error.rs
  • rs/moq-net/src/server.rs
  • rs/moq-relay/src/cluster.rs
  • rs/moq-relay/src/config.rs
  • rs/moq-relay/src/connection.rs
  • rs/moq-relay/src/lib.rs
  • rs/moq-relay/src/limits.rs
  • rs/moq-relay/src/relay.rs
  • rs/moq-relay/src/settings.rs
  • rs/moq-relay/src/uring.rs
  • rs/moq-relay/src/websocket.rs
  • rs/moq-relay/tests/auth_lifetime.rs
  • rs/moq-tokio/src/client.rs
  • rs/moq-tokio/src/server.rs

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 351c7671-1a66-45d2-af40-40498054a7ea
📥 Commits

Reviewing files that changed from the base of the PR and between 8d7c53c and 522b282.

📒 Files selected for processing (3)
  • quest/m1/README.md
  • quest/m1/test-flakes-2/interop-close-code.md
  • rs/moq-net/src/server.rs
💤 Files with no reviewable changes (1)
  • quest/m1/README.md

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 0 remain after this review.

Walkthrough

The relay now supports separate announcement and subscription caps for ordinary sessions and peer sessions. It selects limits from the admitted grant and applies them to relay sessions and outbound cluster clients. Session cap closures map to TOO_MANY_REQUESTS in protocol bindings and OBS error handling. Configuration and language-specific documentation describe the limits and the reported error.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 522b2

The reviewed changes establish no concrete regression requiring action before merge. The historical interop note preserves an unresolved cause rather than attributing the failure to request caps.

Pre-merge checks · Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 60.42% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 48 functions across 22 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks (4 passed)
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Title check Passed The title clearly and concisely describes the main change: separate request caps for relay clients and peers.
Description check Passed The description is directly related to the changeset and explains the configurable session and peer caps, protocol error handling, validation, and impact.
Full details: Docstring Coverage

Explanation

Docstring coverage is 60.42% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 48 functions across 22 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch quest/m1/relay-session-limits
✨ Simplify code
  • Commit to this branch
  • Create a new PR
  • 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.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary

Changes: [session] and [peer] relay tables (with flags and env vars) set per-role request caps. Ordinary clients default to 1,000 announcements and 1,000 subscriptions; an admitted peer grant and outgoing cluster links keep 100,000 / 10,000. The policy is applied after admission and before SETUP on the native, WebSocket, and io_uring paths. A structured TooManyRequests protocol kind is added across C (value 25), UniFFI, the wrappers, and OBS.

Decisions (maintainer accepted the recommended picks):

  • Table names [session] / [peer], not [client].
  • Ordinary default 1,000 / 1,000.
  • Builders named with_limits, matching moq_net::Server::with_limits.
  • Peer caps selected by grant.peer alone (upstream already requires peer).

Also in this PR: it completes quest/m1/relay-session-limits.md, points quest/m1/quic/peer-limits.md at the new [peer] table, and records Interop run 38121507310 in quest/m1/test-flakes-2/interop-close-code.md. That run's refused session failure was refused at admission, before this change's code runs.

Validation: just check passes on the head merged with main, and just test interop --all passes. Codex reviewed the code with no findings, and CodeRabbit had no actionable comments. The final push only merges main and adds the quest note.

(Written by Claude Opus 5.5)

@kixelated
kixelated enabled auto-merge October 13, 2026 05:01

@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 522b282 against base 6a988ac, including changes since my previous read-only inspection (no review was published then).

No actionable findings. Reusing the existing cap machinery and selecting policy from the admitted peer grant keeps the change focused and the role boundary clear. Checked native/WebSocket/io_uring admission, outbound cluster and reconnect caps, legacy SETUP request windows, config plumbing, append-only error kinds, and the added regressions.

Verification: GitHub-only static review; no tests run.

@kixelated
kixelated disabled auto-merge October 13, 2026 05:34
@kixelated
kixelated enabled auto-merge October 13, 2026 05:34
@kixelated
kixelated added this pull request to the merge queue Oct 13, 2026
Merged via the queue into main with commit 9a6fa46 Oct 13, 2026
31 of 32 checks passed
@kixelated
kixelated deleted the quest/m1/relay-session-limits branch October 13, 2026 07:15
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