Skip to content

refactor!: pre-bump API polish across the release batch - #2423

Merged
kixelated merged 6 commits into
mainfrom
claude/pre-bump-api-polish
Jul 20, 2026
Merged

refactor!: pre-bump API polish across the release batch#2423
kixelated merged 6 commits into
mainfrom
claude/pre-bump-api-polish

Conversation

@kixelated

@kixelated kixelated commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Why

The dev batch just merged to main and the release-plz bump PR (#2395) is pending. Since almost every core crate is taking a breaking major in that release anyway, this lands the breaking API cleanups now so they ride this bump for free instead of costing another major later. Everything here is a shape/naming/visibility fix or a doc/lint tightening; no behavior changes except where noted.

This is the source-side follow-up to the pre-bump API review. The version bumps themselves stay with release-plz / the manual edits on #2395; no version = is touched here.

What changed

kio (the load-bearing one)

  • Waiter's lazy waker cell was std::cell::OnceCell, which accidentally made Waiter, Pending, and Shared !Sync / !RefUnwindSafe. That !Sync cascades into moq_net::track::Subscriber and the moq-json / moq-mux consumers (it is most of the auto_trait_impl_removed noise in chore: release #2395's semver-checks output). Switched to std::sync::OnceLock — the lazy fast path is preserved (get_or_init is one atomic load) and the auto traits are restored. Added a compile-time Sync assertion so it cannot silently regress again.
  • Dropped the vestigial R: Unpin bound on Consumer::wait (crate::wait never needed it).

moq-net

  • Role is now #[non_exhaustive] (the wire already maps unknown role codes to None, so new roles are anticipated).
  • Deleted the deprecated with_publish / with_consume builder aliases on Client/Server (a major is the canonical removal point; the Request pair was already gone). No live callers.
  • Added Route::announced() so the advertised publish path is one call. Route::new() still defaults announce: false (deliberate — reachable only by exact path); both constructors are now documented so the choice is obvious.
  • Renamed bandwidth::Producer::close(err)abort(err) to match the crate-wide idiom (abort = terminal-with-error, finish = graceful).
  • Moved serde_json to dev-dependencies (only used under #[cfg(test)]).
  • Documented every public item and turned on #![warn(missing_docs)] (was ~74 holes, incl. the entire new track::Request reserve flow and the broadcast module doc). Removed the em dashes from prose. Reworded the Timescale::MICRO doc that read as if it were the crate default (it is MILLI).

moq-token

  • Error and KeyError are now #[non_exhaustive] (this release adds variants to both, which tripped the exhaustive-enum lint).

moq-native

  • Backoff config and the Status enum are now #[non_exhaustive].

libmoq (C ABI)

  • One verb per concept: _free now always means "release a value handed to the caller", _close always means "stop a task/subscription". Renamed moq_consume_{frame,track_frame,datagram,json_value}_close_free.
  • Catalog section accessors moved into the family that owns the handle: moq_catalog_section_count/_at and moq_catalog_get_sectionmoq_consume_catalog_section_count/_at and moq_consume_catalog_section.
  • moq.h regenerated; cpp/obs, the C smoke client, and the docs reconciled.

moq-stats

  • Renamed the producer config ConfigProducerConfig so it reads unambiguously next to ConsumerConfig before 0.1.0 freezes the name. Fixed the traffic_track doc that mixed the publisher/subscriber roles.

hang

  • Accept the pre-0.20 displayRatioWidth/displayRatioHeight catalog keys as serde aliases for the renamed displayAspectWidth/Height fields, so an old catalog still decodes its aspect ratio instead of silently dropping it. Emitted names stay the new ones. Adds a legacy-decode regression test.

moq-mux

  • Flattened the stuttering container::ts::catalog::Catalog trait to ts::Catalog: the catalog submodule is now private and its surface (Catalog, Mpegts, Track, ...) is re-exported flat at ts, clearing the foo::foo::Foo path without a bespoke trait name and matching the hang::Catalog / msf::Catalog family.
  • Documented that Container::poll_read/read may yield an empty batch as a poll-again state and that only None ends the group (both in-tree callers already loop over empties, so this is a contract clarification, not a behavior change).

moq-hls / moq-rtc / moq-rtmp / moq-srt

  • hls: Broadcaster::new returns crate::Result instead of leaking moq_mux::Error; the internally-built playlist Snapshot/Segment/render_media are now pub(crate) (no external users, and it dissolves the collision with segments::Segment); the renditions::Event cursor enum is #[non_exhaustive].
  • rtc: re-export axum and url (leaked in router/dial signatures) with the major-bump caveat; the empty client::whep/whip submodules are now private; Client::new and every Error variant documented.
  • rtmp / srt: take path: impl AsPath uniformly across every publish/pull/accept entry point so the mirrored surfaces read consistently; origin ownership left as each call site actually uses it.
  • #![warn(missing_docs)] turned on across all four.

Not done here (deliberate follow-ups)

  • Version bumps stay with release-plz / the manual edits on chore: release #2395. Notably: moq-ffi should be 0.3.0 not the proposed 0.2.34 patch, and moq-relay/moq-cli should be hand-capped to patch per policy — those are edits to the release PR, not this branch.
  • js/hang needs the matching displayRatioWidth/Height alias (a zod preprocess, not a serde attribute) so JS consumers decode old catalogs too. It belongs with the paired @moq/* version bump PR, not this Rust branch.
  • moq-mux Carrier bound relaxation: the trait still bounds the format-agnostic import::Container<E>, so every catalog extension carries an MPEG-TS impl even when TS is unused. Untangling that from the shared ContainerImpl enum is a deeper refactor left for a follow-up.

Verification

just fix + just check (whole workspace) exit 0, and RUSTDOCFLAGS="-D warnings" cargo doc is clean for every touched crate. Per-crate test runs pass (kio 18, moq-net 636, moq-mux 385, hang 31 incl. the new legacy-decode test, moq-stats 14, plus the gateways). The three #[non_exhaustive] additions forced conservative match arm updates in moq-relay, moq-bench, and moq-gst, all included.

🤖 Generated with Claude Code

(written by Opus 4.8)

kixelated and others added 4 commits July 20, 2026 13:10
…native

Land breaking API cleanups so they ride the pending semver release
instead of costing another major later.

kio: restore Sync/RefUnwindSafe on Waiter/Pending/Shared by switching the
lazy waker cell from OnceCell to OnceLock (the lazy fast path is preserved);
add a compile-time Sync assertion so it cannot silently regress. Drop the
vestigial R: Unpin bound on Consumer::wait.

moq-net: mark Role #[non_exhaustive] (the wire already tolerates unknown role
codes); delete the deprecated with_publish/with_consume builder aliases; add
Route::announced() so the advertised publish path is one call; rename
bandwidth::Producer::close to abort for crate-wide idiom consistency; move
serde_json to dev-dependencies; document every public item and turn on
warn(missing_docs); remove em dashes from prose.

moq-token: mark Error and KeyError #[non_exhaustive].

moq-native: mark the Backoff config and Status enum #[non_exhaustive].

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Give the C ABI one verb per concept before the 0.4.0 bump. `_free` now
always means "release a value handed to the caller" and `_close` always
means "stop a task or subscription", with no overlap: rename
moq_consume_{frame,track_frame,datagram,json_value}_close to _free.

Move the catalog section accessors into the moq_consume_catalog_* family
that owns the handle's lifecycle: moq_catalog_section_count/_at and
moq_catalog_get_section become moq_consume_catalog_section_count/_at and
moq_consume_catalog_section.

Regenerates moq.h and updates cpp/obs, the C smoke client, and the docs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
moq-stats: rename the producer config Config -> ProducerConfig so it reads
unambiguously next to ConsumerConfig before 0.1.0 freezes the name; fix the
traffic_track doc that mixed the publisher/subscriber roles.

hang: accept the pre-0.20 displayRatioWidth/Height catalog keys as serde
aliases for the renamed displayAspectWidth/Height fields, so an old catalog
still decodes its aspect ratio instead of silently dropping it. Emitted
names stay the new ones. Adds a legacy-decode regression test.

moq-mux: rename the stuttering container::ts::catalog::Catalog trait to
Carrier (it carries the MPEG-TS section) to clear the foo::foo::Foo path and
the three-way Catalog name collision; document that Container::poll_read/read
may yield an empty batch as a poll-again state and only None ends the group.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
moq-hls: Broadcaster::new returns crate::Result instead of leaking
moq_mux::Error; make the internally-built playlist Snapshot/Segment/
render_media pub(crate) (no external users) which also clears the collision
with the recorder segments::Segment; mark the renditions Event cursor enum
#[non_exhaustive].

moq-rtc: re-export axum and url (leaked in router/dial signatures) with the
major-bump caveat; make the empty client whep/whip submodules private;
document Client::new and every Error variant.

moq-rtmp, moq-srt: take path: impl AsPath uniformly across every publish/
pull/accept entry point so the mirrored surfaces read consistently; origin
ownership left as each call site actually uses it.

Turn on warn(missing_docs) across all four crates.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@sourcery-ai sourcery-ai 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.

Sorry @kixelated, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@kixelated, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 19 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 33b84335-0d75-4642-9b3a-cd7ccc836057

📥 Commits

Reviewing files that changed from the base of the PR and between 4642fab and f8606ce.

📒 Files selected for processing (1)
  • rs/moq-gst/src/sink/session.rs

Walkthrough

The changes rename consumed-resource and catalog-section C APIs, update all callers and tests, and correct video-frame cleanup paths. They add legacy catalog-key deserialization, thread-safe waiter initialization, future-status handling, and public API adjustments across media, statistics, network, HLS, RTC, RTMP, and SRT crates. Deprecated builder aliases are removed, several types and modules change visibility or exhaustiveness, and documentation linting plus Rustdoc clarifications are added throughout.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 is concise and broadly matches the pre-bump API cleanup theme of the changeset.
Description check ✅ Passed The description directly matches the workspace-wide API, docs, and API-surface cleanup changes in the PR.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/pre-bump-api-polish

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
rs/moq-net/src/client.rs (1)

39-40: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Restore deprecated builder aliases.

As per coding guidelines, "deprecated public items must have both #[doc(hidden)] and #[deprecated(note = "...")]" and you must "keep deprecated paths functional but hidden from published surfaces." The removal of the with_publish and with_consume aliases violates this rule. Please restore them to maintain backward compatibility.

♻️ Proposed fix
+	#[deprecated(note = "use with_publisher")]
+	#[doc(hidden)]
+	pub fn with_publish(self, publish: impl Consume<origin::Consumer>) -> Self {
+		self.with_publisher(publish)
+	}
+
+	#[deprecated(note = "use with_subscriber")]
+	#[doc(hidden)]
+	pub fn with_consume(self, subscribe: origin::Producer) -> Self {
+		self.with_subscriber(subscribe)
+	}
🤖 Prompt for 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.

In `@rs/moq-net/src/client.rs` around lines 39 - 40, Restore the deprecated public
builder aliases with_publish and with_consume, keeping them functional as
aliases of the current publish/consume methods. Mark both aliases with
#[doc(hidden)] and #[deprecated(note = "...")] using the project’s established
deprecation wording, while leaving the replacement methods unchanged.

Source: Coding guidelines

🤖 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.

Outside diff comments:
In `@rs/moq-net/src/client.rs`:
- Around line 39-40: Restore the deprecated public builder aliases with_publish
and with_consume, keeping them functional as aliases of the current
publish/consume methods. Mark both aliases with #[doc(hidden)] and
#[deprecated(note = "...")] using the project’s established deprecation wording,
while leaving the replacement methods unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 99b47dbb-67b5-4f17-8cfd-3bd2b3eb7419

📥 Commits

Reviewing files that changed from the base of the PR and between 3c07334 and 454aa4d.

📒 Files selected for processing (64)
  • cpp/obs/src/moq-source.cpp
  • doc/concept/layer/hang.md
  • doc/lib/c/index.md
  • rs/CLAUDE.md
  • rs/hang/src/catalog/video/mod.rs
  • rs/kio/src/consumer.rs
  • rs/kio/src/waiter.rs
  • rs/libmoq/README.md
  • rs/libmoq/src/api.rs
  • rs/libmoq/src/test.rs
  • rs/moq-bench/src/connection.rs
  • rs/moq-gst/src/sink/session.rs
  • rs/moq-hls/src/export/mod.rs
  • rs/moq-hls/src/export/playlist.rs
  • rs/moq-hls/src/export/renditions.rs
  • rs/moq-hls/src/lib.rs
  • rs/moq-mux/src/container/consumer.rs
  • rs/moq-mux/src/container/mod.rs
  • rs/moq-mux/src/container/ts/catalog.rs
  • rs/moq-mux/src/container/ts/export.rs
  • rs/moq-mux/src/container/ts/export_test.rs
  • rs/moq-mux/src/container/ts/import.rs
  • rs/moq-mux/src/import/container.rs
  • rs/moq-native/src/client.rs
  • rs/moq-native/src/reconnect.rs
  • rs/moq-native/src/server.rs
  • rs/moq-net/Cargo.toml
  • rs/moq-net/src/client.rs
  • rs/moq-net/src/coding/decode.rs
  • rs/moq-net/src/coding/encode.rs
  • rs/moq-net/src/coding/varint.rs
  • rs/moq-net/src/error.rs
  • rs/moq-net/src/ietf/adapter.rs
  • rs/moq-net/src/ietf/properties.rs
  • rs/moq-net/src/ietf/subscribe_namespace.rs
  • rs/moq-net/src/lib.rs
  • rs/moq-net/src/lite/connecting.rs
  • rs/moq-net/src/lite/priority.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/origin.rs
  • rs/moq-net/src/model/time.rs
  • rs/moq-net/src/model/track.rs
  • rs/moq-net/src/path.rs
  • rs/moq-net/src/server.rs
  • rs/moq-net/src/setup.rs
  • rs/moq-net/src/version.rs
  • rs/moq-relay/src/connection.rs
  • rs/moq-relay/src/stats.rs
  • rs/moq-rtc/src/client/mod.rs
  • rs/moq-rtc/src/error.rs
  • rs/moq-rtc/src/lib.rs
  • rs/moq-rtmp/src/dial.rs
  • rs/moq-rtmp/src/lib.rs
  • rs/moq-rtmp/src/server.rs
  • rs/moq-srt/src/dial.rs
  • rs/moq-srt/src/lib.rs
  • rs/moq-srt/src/server.rs
  • rs/moq-stats/src/consume.rs
  • rs/moq-stats/src/lib.rs
  • rs/moq-stats/src/produce.rs
  • rs/moq-token/src/error.rs
  • test/smoke/clients/c/subscribe.c
💤 Files with no reviewable changes (3)
  • rs/moq-native/src/client.rs
  • rs/moq-native/src/server.rs
  • rs/kio/src/consumer.rs

Name the MPEG-TS catalog-carriage capability ts::Catalog: make the `catalog`
submodule private and re-export its surface flat at the `ts` module, so the
trait and its section types read as ts::Catalog, ts::Mpegts, ts::Track, ...
instead of stuttering under container::ts::catalog. This clears the earlier
foo::foo::Foo path without inventing a bespoke trait name, and lines up with
the hang::Catalog / msf::Catalog family.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kixelated
kixelated enabled auto-merge (squash) July 20, 2026 21:29
moq-native's Status became #[non_exhaustive], so the ConnectionStatus mapping
in the reconnect loop needs a wildcard. Map any non-Connected state to
Disconnected (no behavior change today; future variants fall through safely).
moq-gst doesn't build on the macOS dev shell (no GStreamer), so this only
surfaced in CI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kixelated
kixelated merged commit 5e72d2d into main Jul 20, 2026
3 checks passed
@kixelated
kixelated deleted the claude/pre-bump-api-polish branch July 20, 2026 21:50
@moq-bot moq-bot Bot mentioned this pull request Jul 20, 2026
This was referenced Jul 22, 2026
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