Skip to content

refactor(quic)!: one Limits type for both QUIC runtimes - #5871

Merged
kixelated merged 5 commits into
mainfrom
quic-limits-one-place
Oct 17, 2026
Merged

kixelated merged 5 commits into
mainfrom
quic-limits-one-place

Conversation

@kixelated

@kixelated kixelated commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Supersedes #5735, which stays open as a reference draft. This rebuilds the receive-memory bound for quest/m1/quic/receive-memory.md around a receive lease. It also carries the Bun sender, the receive-credit tests, and benchmark_receive_windows from #5752.

What changes

Bytes now stay in the transport, and moq-net never holds credit. A reader leases a stream's unconsumed bytes and returns their credit with consume(n) once a whole unit is parsed and handed off. The connection window therefore bounds every incomplete header and frame.

The connection window can fill with incomplete messages that none can finish. When that happens, the tokio and io_uring drivers evict the lowest-ranked stream, the newest one on a tie. Eviction drops the stream's bytes, returns its credit through MAX_DATA, and fails the stream's next lease with Evicted. moq-net then stops the stream with its own code. There is no timeout and no new peer signal.

Public API

moq-net transport::poll:

pub trait RecvStream: 'static {
    type Error: Error;
    type Lease<'a>: Lease where Self: 'a;
    fn poll_lease(&mut self, cx: &mut Context<'_>, want: usize) -> Poll<Result<Self::Lease<'_>, Self::Error>>;
    fn set_priority(&mut self, priority: i64); // higher keeps the stream longer
    fn stop(&mut self, code: u32);
    fn poll_read_chunk(&mut self, cx, max) -> ...; // provided
    fn read_chunk(&mut self, max) -> ReadChunk<'_, Self>; // provided
}
pub trait Lease {
    fn len(&self) -> usize;
    fn is_fin(&self) -> bool;
    fn chunks(&self) -> impl Iterator<Item = &[u8]>;
    fn take(&mut self, max: usize) -> Bytes; // keeps credit until consume
    fn consume(self, n: usize);
    // provided: is_empty, chunk, buf
}
pub trait Chunks: 'static { poll_read_chunk, stop }  // plain readers
pub struct Buffered<S: Chunks>; pub struct BufferedLease<'a>;
pub const MIN_RECEIVE_WINDOW: u64;
  • Removed from RecvStream: poll_read, poll_read_buf, poll_closed, read, read_buf, closed, Read and ReadBuf. A lease with is_fin replaces the end observation.
  • Dropping a lease consumes nothing. A want beyond the stream's window is an error, not a wait.
  • iroh, WebAssembly, qmux (WebSocket, TCP, WebRTC), FFI and the memory transport implement Chunks and read through Buffered, which bounds nothing (documented).
  • New CloseKind::Evicted, which maps to the existing Error::Evicted.
  • New priority::{RECV_CONTROL, recv_group}.
  • moq-tokio: the driver RecvStream::poll_lease and set_priority, and driver::Lease<'a>. The quic web RecvStream implements the moq-net trait natively. Deleted read_held, poll_read_held and driver::Credit.
  • moq-uring: quic::RecvStream::poll_lease and set_priority, and quic::Lease<'a>. Deleted Credit, poll_read_held and the read-ahead backlog. Deleted Connection::stats(); the stats go through the moq-net trait. Added Error::{Evicted, TooLarge}.
  • moq-quic: RecvStream::{lease, take, consume, set_priority}, Leased, LeaseError and Streams::leased. Deleted the public Credit, Chunks::hold (now a private withhold) and Connection::release. CreditStats is now { leased, available }.
  • The Grouped transport trait (tokio and uring) gains type Recv; fn recv(...).

Configuration:

  • The tokio DEFAULT_RECEIVE_WINDOW and the uring connection window are 128 MiB; they were 64 MiB and 16 MiB.
  • The stream window now follows the connection window unless it is set (tokio backend, iroh, uring).
  • A connection window below MIN_RECEIVE_WINDOW is refused at config load, including [peer.quic].
  • The peer default stays at 640 MiB.

Wire impact

None to message framing or codes. A receiver may now STOP_SENDING an evicted stream with moq-net's existing Evicted code. No draft changes.

Receive ranks

  • Control streams rank i64::MAX.
  • A data stream ranks 0 until its header is decoded.
  • After that it ranks recv_group(subscription priority, group sequence), so the oldest group of the lowest-priority subscription goes first.

Benchmarks against main

Each pair was run back to back on the same machine, with branch numbers taken before the latest main merge. Positive numbers mean slower.

Bench Range Notes
uring session_lite (native lease path) -2% to -54% oneshot -54%, all-on -11%, all-off -6%
moq-net memory (Buffered) -2% to -23% 1 MiB × 128 streams -23%
moq-quic receive_stop -1% to -38%
moq-quic receive_loss and receive_reset mostly flat one +13% outlier at 1024 resets
moq-net frame_recv (Buffered, 1200-byte chunks) +1% to +15% typical one +33% outlier, upfront 256 KiB × 64

The frame_recv slowdown is the per-chunk lease overhead (a VecDeque push and pop) on 1200-byte chunks. The first run also caught Buffered reading 64 KiB at a time, which split memory-transport frames and copied them, 15-40× slower at 1 MiB; it is fixed here with a regression test.

Open decisions

  1. Defaults vs refactor(quic)!: one Limits type for both QUIC runtimes #5871. That PR sets 64 MiB connection, 4 MiB stream and 16 MiB send for both runtimes. This PR uses a 128 MiB connection window with the stream window following it. Leased bytes return stream credit as they are read, so a smaller stream window only adds round trips, and only the connection window needs MIN_RECEIVE_WINDOW. Whichever PR lands second reconciles the defaults onto one Config::resolve. Recommendation: keep 128 MiB, and let the stream window follow the connection window.
  2. The receive rank is one i64, so it compares subscription priorities across broadcasts. Ranking within broadcast fairness domains first is a quest follow-up.
  3. Control streams outrank all media, so a peer stuck on partial control requests makes media yield first.
  4. The impaired-lane drills now set only the stream window, so they no longer exercise MAX_DATA pressure there.
  5. STOP_SENDING is lazy: eviction stops the stream's reads locally, and the code goes out when moq-net calls stop. Mixing a lease and plain reads on one stream is unsupported.

Checks

  • just check passes.
  • just test interop --all: see below.
  • The receive-credit tests pass, including both Bun arms.
  • 10 stress iterations of the lease and eviction tests passed.

🤖 Generated with Claude Code

kixelated and others added 4 commits October 17, 2026 08:24
moq-quic owns `Limits` (validated, `#[non_exhaustive]`, `None` leaves a
limit unchanged) and `Connection::set_limits`. moq-tokio and moq-uring
re-export it as `quic::Limits`, and both expose
`quic::Connection::set_limits(Limits) -> Result<(), quic::Error>`.
`Request::quic()` replaces `set_quic_limits` and `Error::QuicLimits`.

`[quic] max_streams = 0` is refused, and the connection receive window
default resolves in `quic::Config::resolve`, so io_uring workers run the
documented 64 MiB instead of 16 MiB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`quic::Config::resolve` now fills a 4 MiB per-stream receive window and
a 16 MiB send window alongside the 64 MiB connection window, so the
tokio, iroh, and io_uring backends run identical windows for the same
`[quic]` section instead of each falling back to its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	cpp/obs/src/moq-settings.cpp
#	go/wrapper/client.go
#	rs/moq-ffi/src/session.rs
@kixelated
kixelated marked this pull request as ready for review October 17, 2026 17:18
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 17, 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-17T17:21:20.946138Z 27b2db1 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 17, 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 36 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
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 208eb75e-5c64-4805-ac3a-f4e5fdbedc70
📥 Commits

Reviewing files that changed from the base of the PR and between 27b2db1 and f2b3e6f.

⛔ Files ignored due to path filters: 1
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing: 26
  • doc/bin/relay/config.md
  • go/wrapper/client.go
  • go/wrapper/server.go
  • quest/m2/rate-quic.md
  • rs/moq-ffi/src/session.rs
  • rs/moq-quic/README.md
  • rs/moq-quic/src/connection/mod.rs
  • rs/moq-quic/src/lib.rs
  • rs/moq-quic/src/limits.rs
  • rs/moq-quic/src/tests/characterize/limits.rs
  • rs/moq-relay/Cargo.toml
  • rs/moq-relay/src/cluster.rs
  • rs/moq-relay/src/connection.rs
  • rs/moq-relay/src/limits.rs
  • rs/moq-relay/src/uring.rs
  • rs/moq-relay/tests/integration/peer_limits.rs
  • rs/moq-tokio/src/error.rs
  • rs/moq-tokio/src/iroh.rs
  • rs/moq-tokio/src/quic.rs
  • rs/moq-tokio/src/quic/backend.rs
  • rs/moq-tokio/src/quic/driver/connection.rs
  • rs/moq-tokio/src/server.rs
  • rs/moq-uring/src/error.rs
  • rs/moq-uring/src/quic/driver/connection.rs
  • rs/moq-uring/src/quic/mod.rs
  • rs/moq-uring/src/quic/web.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: a74ffb76-89c2-4893-b797-55c997ba02d3
📥 Commits

Reviewing files that changed from the base of the PR and between 8332188 and 27b2db1.

⛔ Files ignored due to path filters: 1
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing: 26
  • doc/bin/relay/config.md
  • go/wrapper/client.go
  • go/wrapper/server.go
  • quest/m2/rate-quic.md
  • rs/moq-ffi/src/session.rs
  • rs/moq-quic/README.md
  • rs/moq-quic/src/connection/mod.rs
  • rs/moq-quic/src/lib.rs
  • rs/moq-quic/src/limits.rs
  • rs/moq-quic/src/tests/characterize/limits.rs
  • rs/moq-relay/Cargo.toml
  • rs/moq-relay/src/cluster.rs
  • rs/moq-relay/src/connection.rs
  • rs/moq-relay/src/limits.rs
  • rs/moq-relay/src/uring.rs
  • rs/moq-relay/tests/integration/peer_limits.rs
  • rs/moq-tokio/src/error.rs
  • rs/moq-tokio/src/iroh.rs
  • rs/moq-tokio/src/quic.rs
  • rs/moq-tokio/src/quic/backend.rs
  • rs/moq-tokio/src/quic/driver/connection.rs
  • rs/moq-tokio/src/server.rs
  • rs/moq-uring/src/error.rs
  • rs/moq-uring/src/quic/driver/connection.rs
  • rs/moq-uring/src/quic/mod.rs
  • rs/moq-uring/src/quic/web.rs
💤 Files with no reviewable changes: 1
  • rs/moq-uring/src/error.rs

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

Walkthrough

The change adds shared validation and live updates for QUIC stream and flow-control limits. Tokio now resolves explicit defaults of 64 MiB for connection receive windows, 4 MiB for stream receive windows, and 16 MiB for send windows, and rejects a stream limit of zero. Relay peer limits use the shared API, and limit-setting errors propagate from accepted connections.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 27b2d

No actionable issue remains in the reviewed changes; the PR is ready to merge after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Description check Warning The description focuses on receive leases, stream eviction, and moq-net API changes that are not present in the changeset. The actual changes unify QUIC Limits types, validation, defaults, and `se… Replace the description with an accurate summary of the unified moq_quic::Limits type, centralized QUIC defaults, validation behavior, Connection::set_limits, runtime re-exports, and relay integration changes.
Passed Passed checks: 4 passed
Check name Status Explanation
Docstring Coverage Passed Docstring coverage is 88.46% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 52 functions across 21 files. (4 skipped: 4…
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 accurately summarizes the main change: one shared Limits type is introduced for both QUIC runtimes.
Full details: Docstring Coverage

Explanation

Docstring coverage is 88.46% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 52 functions across 21 files. (4 skipped: 4 unsupported.)

Full details: Description check

Explanation

The description focuses on receive leases, stream eviction, and moq-net API changes that are not present in the changeset. The actual changes unify QUIC Limits types, validation, defaults, and set_limits APIs.

Resolution

Replace the description with an accurate summary of the unified moq_quic::Limits type, centralized QUIC defaults, validation behavior, Connection::set_limits, runtime re-exports, and relay integration changes.

✨ Finishing Touches: 💡 1
⚔️ Resolve merge conflicts: 💡
  • Resolve merge conflict in branch quic-limits-one-place
✨ 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
kixelated added this pull request to the merge queue Oct 17, 2026
Merged via the queue into main with commit 27993bc Oct 17, 2026
13 checks passed
@kixelated
kixelated deleted the quic-limits-one-place branch October 17, 2026 19:10
kixelated added a commit that referenced this pull request Oct 17, 2026
…5871

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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