Skip to content

Gate moq-net async helpers and sessions behind a default feature - #5503

Merged
kixelated merged 6 commits into
mainfrom
quest/m1/net-async-feature
Oct 14, 2026
Merged

kixelated merged 6 commits into
mainfrom
quest/m1/net-async-feature

Conversation

@kixelated

@kixelated kixelated commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

moq-net pulls native runtime dependencies even when a caller only wants its explicit-time model. Add a default-on async feature for async helpers, the announcement Stream adapter, time::run, and whole Lite/IETF sessions. Native model-only consumers can disable default features and drive the existing poll APIs without Tokio or web-async.

The origin's run_front/serve_front and explicit-time driver remain available. Shared codecs and version/error types stay compiled; unused session-facing hooks have narrowly scoped allowances rather than a crate-wide dead-code suppression. Helper/session tests follow their feature, while public integration tests serve media, resolve a routed broadcast, and tear down an origin using only explicit polls.

Route resolution poll core

Consumer::routed_broadcast held the only race-safe resolver (watch the covering routes, ask, re-ask when they move), and it was an async fn gated behind async, so a poll-only consumer would have had to reimplement it (Codex review). It now returns kio::Pending<origin::Routing>, a kio::Task that owns that state machine, the same shape as request_broadcast -> Requesting, subscribe -> Subscribing, and fetch_group -> Fetching. kio::Pending needs no runtime, so the method stays available without async and there is no separate gated wrapper. Existing .await callers are unchanged.

Decisions (maintainer and agent):

  • Move route resolution into a poll core that is always available. ✅ (maintainer)
  • Shape: return kio::Pending<Routing> from routed_broadcast, mirroring request_broadcast. ✅ Alternative not taken: keep async fn routed_broadcast gated and add a second always-available constructor for the Task (two names for one operation).
  • Routing implements only kio::Task, like track::Fetching; no inherent poll_ok, since its state needs &mut self.

Public API

  • New Cargo feature async, on by default. With default-features = false, async helpers, the announcement Stream adapter, time::run, Client/Server/Session, and the session Driver are unavailable. Default callers keep the same API and behavior.
  • origin::Consumer::routed_broadcast changes from async fn(&self, impl AsPath) -> Result<broadcast::Consumer, Error> to fn(&self, impl AsPath) -> kio::Pending<origin::Routing> (same Output). It no longer borrows the consumer or path, and it is available without async.
  • New origin::Routing, a kio::Task resolving to Result<broadcast::Consumer, Error>.

Wire: none. JS needs no parity change because this is Rust Cargo feature selection and the default wire implementations are unchanged.

CI

just rs net-features (sh/rs/net-features.sh) asserts the no-default dependency tree has no tokio or web-async, runs clippy, rustdoc, and the moq-net suite without default features, and builds a WASM leaf consumer. It was nightly-only through just rs features; PR checks now run it whenever moq-net is selected, alongside tokio-features, since any dependent unifies the default feature back on, and whenever the script itself changes, like media-features.sh.

Validation

Rebased on main after #5505 (session_setup.rs deletion, replacement.rs rename, the track.rs is_live doc, quest/m1/time/net.md: its satisfied Required entries are dropped). just check passed on head 3968eaf422e88848172346538dc73b904ddddbd3, including 7,440 default Rust tests and the no-default lane (826 tests, dependency assertion, WASM consumer build).

The completed quest and its dependency links are removed. The existing Controlled time migration can preserve this feature boundary when it adopts moq-clock.

(Written by Claude Opus 5.5)

@coderabbitai

coderabbitai Bot commented Oct 14, 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 13 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: 50a03957-dd83-4139-90a5-456eb622e92c
📥 Commits

Reviewing files that changed from the base of the PR and between 3dabaaf and 3968eaf.

📒 Files selected for processing: 90
  • doc/lib/rs/moq-net.md
  • quest/m1/README.md
  • quest/m1/net-async-feature.md
  • quest/m1/time/README.md
  • quest/m1/time/net.md
  • rs/justfile
  • rs/moq-net/Cargo.toml
  • rs/moq-net/README.md
  • rs/moq-net/benches/session.rs
  • rs/moq-net/src/auth.rs
  • rs/moq-net/src/coding/codes.rs
  • rs/moq-net/src/coding/decode.rs
  • rs/moq-net/src/coding/encode.rs
  • rs/moq-net/src/coding/mod.rs
  • rs/moq-net/src/coding/varint.rs
  • rs/moq-net/src/coding/version.rs
  • rs/moq-net/src/epoch.rs
  • rs/moq-net/src/error.rs
  • rs/moq-net/src/goaway.rs
  • rs/moq-net/src/ietf/auth.rs
  • rs/moq-net/src/ietf/mod.rs
  • rs/moq-net/src/ietf/peer.rs
  • rs/moq-net/src/ietf/token.rs
  • rs/moq-net/src/lib.rs
  • rs/moq-net/src/lite/compress.rs
  • rs/moq-net/src/lite/mod.rs
  • rs/moq-net/src/lite/setup.rs
  • rs/moq-net/src/model/bandwidth.rs
  • rs/moq-net/src/model/broadcast.rs
  • rs/moq-net/src/model/follow.rs
  • rs/moq-net/src/model/frame.rs
  • rs/moq-net/src/model/group.rs
  • rs/moq-net/src/model/mod.rs
  • rs/moq-net/src/model/origin.rs
  • rs/moq-net/src/model/resume.rs
  • rs/moq-net/src/model/track.rs
  • rs/moq-net/src/path/mod.rs
  • rs/moq-net/src/setup.rs
  • rs/moq-net/src/stats.rs
  • rs/moq-net/src/time.rs
  • rs/moq-net/src/util.rs
  • rs/moq-net/src/version.rs
  • rs/moq-net/tests/announce_covering_route.rs
  • rs/moq-net/tests/announce_to_serve.rs
  • rs/moq-net/tests/auth.rs
  • rs/moq-net/tests/broadcast_close.rs
  • rs/moq-net/tests/catalog_acquisition.rs
  • rs/moq-net/tests/datagram.rs
  • rs/moq-net/tests/dial_split_horizon.rs
  • rs/moq-net/tests/drained_claim.rs
  • rs/moq-net/tests/empty_group.rs
  • rs/moq-net/tests/extensions.rs
  • rs/moq-net/tests/fetch_cancel.rs
  • rs/moq-net/tests/fetch_from_feed.rs
  • rs/moq-net/tests/fetch_only.rs
  • rs/moq-net/tests/finished_broadcast_mock.rs
  • rs/moq-net/tests/finite_relay.rs
  • rs/moq-net/tests/goaway.rs
  • rs/moq-net/tests/group_charge.rs
  • rs/moq-net/tests/group_order.rs
  • rs/moq-net/tests/head_fetch.rs
  • rs/moq-net/tests/history_groups.rs
  • rs/moq-net/tests/idle_cancel_refetch.rs
  • rs/moq-net/tests/idle_session.rs
  • rs/moq-net/tests/late_lower_group.rs
  • rs/moq-net/tests/loom.rs
  • rs/moq-net/tests/mesh_withdraw.rs
  • rs/moq-net/tests/model.rs
  • rs/moq-net/tests/multi_cdn.rs
  • rs/moq-net/tests/quiet_catalog.rs
  • rs/moq-net/tests/rejoin.rs
  • rs/moq-net/tests/replacement.rs
  • rs/moq-net/tests/request_caps.rs
  • rs/moq-net/tests/restart.rs
  • rs/moq-net/tests/route_change.rs
  • rs/moq-net/tests/session_close.rs
  • rs/moq-net/tests/session_panic.rs
  • rs/moq-net/tests/settled_end_survives_abort.rs
  • rs/moq-net/tests/subscribe_tracks.rs
  • rs/moq-net/tests/subscription_end_integrity.rs
  • rs/moq-net/tests/track_abort_over_session.rs
  • rs/moq-net/tests/track_info_cancel.rs
  • rs/moq-net/tests/track_stream_demand.rs
  • rs/moq-net/tests/track_tail.rs
  • rs/moq-net/tests/unannounce_release.rs
  • rs/moq-net/tests/untimed.rs
  • rs/moq-net/tests/wasm.rs
  • rs/moq-net/tests/wide_sequence.rs
  • sh/rs/net-features.sh
  • sh/rs/select.sh
  • 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 14, 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-14T19:38:23.259424Z 57719eb Manual request
ℹ️ 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

Completed the async feature quest. Clean head 1ead2779a1b30736d36185419562628925baa1a8 passed strict local checks against 071c6f85e9cece7ab1bc35ca55b5455867ca3aef; the no-default lane passed 821 tests and a WASM consumer build. The composed #5496 compatibility check passed 823 tests.

Default callers keep their API and behavior. Opting out removes async helpers, the announcement Stream adapter, and sessions; the explicit-time origin/model drivers remain. Wire and JS behavior are unchanged. The existing Controlled time migration is the next scoped follow-up; no decision remains.

(Written by GPT-6)

@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: 1ead2779a1

ℹ️ 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/model/origin.rs Outdated
Comment on lines 5095 to 5096
#[cfg(feature = "async")]
pub async fn routed_broadcast(&self, path: impl AsPath) -> Result<broadcast::Consumer, Error> {

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 Keep route-resolution logic available without async

When a caller disables default features as newly documented, this gate removes the only race-safe broadcast resolver. Unlike the thin async wrappers elsewhere, routed_broadcast contains the substantive watch-before-request retry loop that handles route retraction and replacement, and there is no poll_routed_broadcast equivalent. A poll-driven consumer must therefore duplicate this logic and can easily miss a route change. Move the state machine into a poll-based core and gate only its async wrapper.

AGENTS.md reference: rs/AGENTS.md:L19-L24

Useful? React with 👍 / 👎.

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.

Fixed in b9094c8. The watch-then-ask loop now lives in origin::Routing, a kio::Task, and routed_broadcast returns kio::Pending<Routing> (the request_broadcast shape), so it stays available without async. tests/model.rs covers it with explicit polls only: park on an unroutable path, resolve after the announce, and end with Closed on teardown.

(Written by Claude Opus 5.5)

kixelated and others added 5 commits October 14, 2026 11:57
Co-Authored-By: GPT-6 <noreply@openai.com>
Co-Authored-By: GPT-6 <noreply@openai.com>
`routed_broadcast` was an async-only retry loop, so a consumer without the
`async` feature had to reimplement route resolution. It now returns
`kio::Pending<origin::Routing>`, a Task that watches the covering routes and
re-asks when they move, like `request_broadcast` returns `Requesting`.

PR checks run the no-default moq-net lane whenever moq-net is selected.

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/net-async-feature branch from 93de5e6 to 57719eb Compare October 14, 2026 19:23

@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: 57719eb against merge base 865f36e, including the runtime-free model boundary and upstream integration. No actionable bugs found.

The explicit Routing pending state addresses the existing public-polling finding (#5503 (comment)). It registers the change watcher before requesting, releases an Unroutable request before parking, and observes teardown through wakeups and Dropped-to-Closed handling. The public re-export and explicit-poll regression cover the intended API.

Direction: keeping the model usable without the native runtime is appropriate. The isolated no-default-feature lane checks dependency boundaries, lint/docs/tests and a WASM consumer; the current rebase preserves the previously inspected PR-only changes.

Verification: static GitHub inspection only; no tests executed. Current-head workflows were still running, so this review does not establish passing CI.

@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: 57719eb22b

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

use futures::FutureExt;

#[test]
#[cfg(feature = "async")]

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 Keep core model tests enabled without async

When the new --no-default-features lane runs, this gate and the repeated gates throughout group.rs and track.rs compile out the core cache, fetch, recovery, expiry, and demand tests, even though those behaviors remain available in the runtime-free model. The lane therefore validates compilation and only the small new integration test rather than exercising the logic under the feature boundary where regressions can occur. Keep the model tests enabled by polling directly or exposing their convenience helpers under cfg(test). (Written by GPT-5.6 Sol)

AGENTS.md reference: rs/AGENTS.md:L55-L55

Useful? React with 👍 / 👎.

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.

Declining. The async feature removes wrappers only: the crate has no cfg(not(feature = "async")) branch in any logic, just dead-code allowances. So the cache, fetch, recovery, expiry, and demand code these tests cover compiles identically either way, and the merge gate already runs every one of them under default features. That is what rs/AGENTS.md L55 asks for. Running them a second time without the feature would cover no new code. Ungating would also mean rewriting hundreds of sim-driven async tests or compiling the helpers under cfg(test), which blurs the boundary the no-default lane is there to prove. That lane's job is the boundary itself: the dependency assertion, clippy and rustdoc, the WASM consumer, and the poll-only integration tests in tests/model.rs, now including routed_broadcast.

(Written by Claude Opus 5.5)

Comment thread sh/rs/select.sh Outdated
Comment on lines +124 to +125
# Likewise every dependent turns moq-net's default `async` feature back on.
if wants moq-net; then just rs net-features; fi

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 Run the feature check when its script changes

With a changed-files list containing only sh/rs/net-features.sh, select_packages returns no packages because the path is neither under rs/ nor in the global-path regex, and the empty-package branch exits before this new call. Thus a PR that breaks the feature-check script itself reports rs: no crates affected; skipping. instead of running it. Add this script to the global selector or handle it like media-features.sh. (Written by GPT-5.6 Sol)

Useful? React with 👍 / 👎.

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.

Fixed: select.sh now treats sh/rs/net-features.sh like media-features.sh, so a diff touching only that script runs just rs net-features (verified with a one-line change list).

(Written by Claude Opus 5.5)

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

Copy link
Copy Markdown
Collaborator Author

Iteration summary, final head 3968eaf42:

  • Rebased over main, including fix(net): distinguish live feeds from retained caches #5505 (the track.rs is_live doc conflict), the session_setup.rs deletion, and the replacement.rs rename.
  • Poll core: routed_broadcast now returns kio::Pending<origin::Routing>, a kio::Task that owns the watch-then-ask loop, mirroring request_broadcast, subscribe, and fetch_group. It is available without async; existing .await callers are unchanged. A poll-only test is in tests/model.rs.
  • CI: the no-default lane (no tokio or web-async in the tree, clippy, rustdoc, tests, WASM consumer) runs on PRs whenever moq-net or sh/rs/net-features.sh changes, as well as nightly.
  • Codex review of 57719eb22: I fixed the selector-script finding and declined the gated-tests one, with the reasoning in its thread. The only change since then is that selector fix.
  • just check passed on the final head: 7,440 default Rust tests, plus 826 tests in the no-default lane.

Public API: new default async feature; origin::Consumer::routed_broadcast changes from async fn to fn -> kio::Pending<origin::Routing>; new origin::Routing. Wire: none.

(Written by Claude Opus 5.5)

@kixelated
kixelated enabled auto-merge October 14, 2026 19:52

@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: 3968eaf, focusing on sh/rs/select.sh since 57719eb.

The selector finding is fixed: edits to net-features.sh now reach the isolated feature gate for both script-only and mixed-crate changes, including simultaneous media/net script edits (#5503 (comment)). The outer dispatcher already includes sh/rs/. No new actionable bugs found.

Direction: focused reuse of the existing script-selection pattern. Routing and the runtime-free API are unchanged. The default suite plus isolated no-default dependency/API checks remains a reasonable boundary; no new alternate model logic was introduced here.

Verification: static GitHub inspection only; no tests executed. The author's reported final-head test pass was not independently reproduced, and current-head CI was still running.

@kixelated
kixelated added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit f367085 Oct 14, 2026
11 of 12 checks passed
@kixelated
kixelated deleted the quest/m1/net-async-feature branch October 14, 2026 20:34
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