feat(kio): add a poll-native Deadline and adopt it in moq-net - #2536
Conversation
Six sites in moq-net hand-rolled a wall-clock deadline inside a `kio::wait` closure, each pinning an async block whose `None` arm was `std::future::pending()`, then fusing it with a separate `fired` flag and an `is_some()` guard. Three moving parts to express "an optional deadline that fires once". `kio::time::Deadline` replaces all of it. Both clock backends behind `web_async::time` (tokio natively, wasmtimer in the browser) already expose `Sleep::is_elapsed` and `Sleep::reset`, so the fuse comes for free and re-arming reuses the allocation instead of boxing a fresh future every loop turn. Construction of the inner `Sleep` is deferred to the first poll, since on native it panics without a live tokio time driver, and only the poll is guaranteed to run inside the executor. The probe interval in lite/publisher no longer pins `interval.tick()` either; `Interval::poll_tick` is already poll-native on both backends. `kio::tokio::Sleep` is superseded: it is native-only, cannot be re-armed or disarmed, and has no fuse. It had no callers in or out of the module, and nothing in the workspace enabled the `tokio` feature. Hidden and deprecated here; removal is a breaking change and belongs on dev. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Sorry @kixelated, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
|
Warning Review limit reached
Next review available in: 12 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
WalkthroughAdds a feature-gated 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches✨ Simplify code
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 |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@rs/kio/src/time.rs`:
- Line 13: Add a doc comment immediately above the public re-export of Duration
and Instant explaining that these types come from web_async::time and
documenting the dependency’s major-version coupling. Keep the existing re-export
unchanged.
- Around line 53-56: Update Time’s after method to use checked Instant
arithmetic instead of Instant::now() + duration. Mirror the existing origin.rs
pattern with an inlined checked_add result, preserving the deadline behavior
while ensuring non-representable durations never panic.
In `@rs/kio/src/tokio.rs`:
- Around line 16-19: Add the #[doc(hidden)] attribute to the deprecated public
Sleep struct, alongside its existing #[deprecated(note = "...")] attribute, so
the item is excluded from generated documentation while preserving the
deprecation notice.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: c4b97578-3c6d-4edd-b521-b8ecbad9d810
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (9)
rs/kio/Cargo.tomlrs/kio/src/lib.rsrs/kio/src/time.rsrs/kio/src/tokio.rsrs/moq-net/Cargo.tomlrs/moq-net/src/ietf/control.rsrs/moq-net/src/ietf/subscriber.rsrs/moq-net/src/lite/publisher.rsrs/moq-net/src/model/origin.rs
- Document that `Duration`/`Instant` are re-exported from `web-async`, so a major bump there is a breaking change for them. - `Deadline::after` now uses checked arithmetic. A duration the clock cannot represent (e.g. `Duration::MAX`) leaves the deadline disarmed instead of panicking on the overflow, matching how `run_front` already treats an unrepresentable linger. - Add the item-level `#[doc(hidden)]` to the deprecated `kio::tokio::Sleep` alongside its `#[deprecated]`, per the repo's deprecation convention. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…cate-announcements-34ef49 `main` replaced the pinned-sleep-plus-`fired` timer scaffolding with `kio::time::Deadline` (#2536) in the two loops this branch also edits. Took main's shape in both and kept this branch's additions on top: the per-track `skip` closure in `serve_track`, and the route-table wording in the announce loop. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* 'main' of https://github.com/moq-dev/moq: (43 commits) feat(cli): add jemalloc heap profiling (moq-dev#2539) feat(kio): add a poll-native Deadline and adopt it in moq-net (moq-dev#2536) test(moq-srt): size the burst test below the SRT sender's drop window (moq-dev#2540) refactor(net): replace the global LRU cache pool with per-track write-time eviction (moq-dev#2526) ci: compile-check the Windows and macOS code paths on PRs (moq-dev#2531) chore(net): require @moq/qmux 0.3.2 for fallback reset codes (moq-dev#2535) fix(hang,watch): deliver non-sequential group ids incrementally (moq-dev#2484) feat(moq-audio): play decoded PCM out a speaker (moq-dev#2529) fix(js/publish): capture video through a worker MediaStreamTrackProcessor (moq-dev#2528) feat(net): surface a peer's stream reset code as a remote error (moq-dev#2510) feat(mux): expose catalog bitrate/jitter measurement as catalog::Estimator (moq-dev#2530) fix(net): release cache-pool registrations so publishers stop leaking (moq-dev#2525) build(deps): bump the github-actions group with 2 updates (moq-dev#2524) build(deps-dev): bump ruff from 0.15.21 to 0.15.22 in the uv group (moq-dev#2523) build(deps): bump the bun group with 2 updates (moq-dev#2522) chore: bump non-Rust package patch versions (moq-dev#2519) fix(hang): reject a non-hex catalog description instead of misreading it (moq-dev#2516) build(deps): bump the github-actions group across 1 directory with 6 updates (moq-dev#2464) refactor(net): poll kio readiness directly (moq-dev#2515) chore: release (moq-dev#2491) ... # Conflicts: # rs/moq-net/src/client.rs
Summary
Six sites in
moq-nethand-rolled a wall-clock deadline inside akio::waitclosure. Each pinned an async block whoseNonearm wasstd::future::pending(), then fused it with a separatefiredflag and anis_some()guard:kio::time::Deadlinecollapses that todeadline.set(at)plusdeadline.poll(waiter).web_async::time(tokio natively, wasmtimer in the browser) already exposeSleep::is_elapsedandSleep::reset, so the fuse comes for free and re-arming reuses the allocation instead of boxing a fresh future every loop turn.Deadline::setis a no-op for the instant it already holds, which is what lets the linger loops inorigin.rsrecompute and re-set their deadline every turn without restarting the countdown. The(true, at) => atarm depends on this.Sleepis deferred to the first poll: on native it panics without a live tokio time driver, and only the poll is guaranteed to run inside the executor. Sonew/setstay callable anywhere, and the runtime requirement lands exactly where it does today.lite/publisher.rsno longer pinsinterval.tick().Interval::poll_tickis already poll-native on both backends and needs no wrapper.kio::tokio::Sleepis superseded: native-only, no re-arm, no disarm, no fuse. It had no callers anywhere, and nothing in the workspace enabled thetokiofeature. Hidden and deprecated here; the removal (plus dropping the optionaltokiodependency) is a breaking change to a published crate and belongs ondevas a follow-up.Net -34 lines across the converted sites.
Public API changes
All additive, so this targets
main.kio::timemodule behind a newtimecargo feature (dep:web-async).kio::time::Deadlinewithnew,at,after,set,deadline,poll,wait, plusDefaultandDebug.kio::time::{Instant, Duration}re-exports fromweb_async::time.kio::tokio::Sleep(#[deprecated]) and hidkio::tokio(#[doc(hidden)]). Not a removal, so not breaking. Verified the warning reaches a caller rather than being swallowed by the#[allow(deprecated)]on the impl block.moq-netgains no public surface; all six converted sites are private.Test plan
Deadlinetests under#[tokio::test(start_paused = true)], covering firing, disarmed-never-fires, fused-once-elapsed, idempotent re-arm, deferred re-arm throughSleep::reset, disarm mid-countdown, and re-arm after disarm.just fixclean,just rs checkclean (clippy-D warnings,cargo fmt --check, rustdoc-D warnings,cargo shear,cargo sort).cargo test -p kio --all-features: 26 pass.cargo test -p moq-net: 557 pass. Fulljust rs test: 1941 pass.cargo check -p kio --features time --target wasm32-unknown-unknownbuilds, pullingwasmtimeras expected. Themoq-netwasm build fails on a pre-existinggetrandombackend error, identical with these changes stashed.Unrelated failure seen while testing
moq-srt'saccepted_socket_sends_a_burst_larger_than_srt_tokio_defaultfailed once in the full run. It is pre-existing and not caused by this change: on a stashed tree it fails 2 of 8 consecutive runs, versus 1 of 5 here. It sends 1024 messages over a real SRT/UDP loopback socket and asserts delivery inside a fixed 3-second wall-clock budget on real timers, so it is timing-sensitive under load. Tracked separately rather than papered over with a longer timeout.Cross-Package Sync
No rows apply. No wire format,
moq-ffi, CLI, or relay config surface changed, andmoq-net's public API is untouched.🤖 Generated with Claude Code
(Written by Opus 5)