Skip to content

libmoq: add moq_origin_consume_announced to wait for a broadcast#1552

Merged
kixelated merged 2 commits into
mainfrom
claude/jolly-babbage-4683ed
May 30, 2026
Merged

libmoq: add moq_origin_consume_announced to wait for a broadcast#1552
kixelated merged 2 commits into
mainfrom
claude/jolly-babbage-4683ed

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Summary

moq_origin_consume does a synchronous lookup that returns BroadcastNotFound (-24) when the broadcast hasn't been announced yet. Right after moq_session_connect, the announcement often arrives after the call, so C consumers have to poll moq_origin_consume in a retry-until-announced loop.

This adds a callback-based variant that waits for the announcement instead of racing it:

  • moq_origin_consume_announced(origin, path, path_len, on_broadcast, user_data) — registers a wait on a specific path, backed by moq_net::OriginConsumer::announced_broadcast (exactly what the stale TODO in origin.rs pointed at). When the broadcast is announced, on_broadcast fires with the broadcast handle (> 0), then a terminal 0.
  • moq_origin_consume_announced_close(task) — cancels a pending wait.

Why callback-based rather than thread-blocking

ffi::enter holds the runtime mutex for the duration of every FFI call, so a call that blocked the caller's thread would stall all other FFI calls (including the close needed to cancel it). The whole libmoq surface is non-blocking/callback-driven, and this follows the existing terminal-callback lifetime contract introduced in #1546:

  • > 0 = live broadcast handle, 0 = clean close (terminal), < 0 = error (terminal).
  • The terminal callback fires even after an explicit *_close, and that's where the caller frees user_data.
  • The broadcast handle is independent: usable with moq_consume_catalog / moq_consume_track, freed with moq_consume_close.

Scope / cross-package sync

Scoped to rs/libmoq (a leaf crate with no in-workspace Rust dependents). The cbindgen header (target/include/moq.h) regenerates with both functions. doc/lib/c is high-level and needs no change; README.md gained the two signatures. The uniffi wrappers (py/swift/kt/go) are unaffected, since Rust ownership handles their lifetimes.

Test plan

  • cargo test -p libmoq (21 pass, incl. new consume_announced_local wait-then-publish and consume_announced_close_cancels)
  • cargo clippy -p libmoq --all-targets clean
  • cargo fmt -p libmoq --check clean
  • cbindgen header regenerates with both new functions

(Written by Claude)

moq_origin_consume does a synchronous lookup that returns BroadcastNotFound
(-24) when the broadcast hasn't been announced yet, forcing C callers to
poll in a retry loop right after connecting. Add a callback-based variant
backed by moq_net::OriginConsumer::announced_broadcast that waits for the
announcement and then delivers the broadcast handle.

A true thread-blocking call isn't viable here: ffi::enter holds the runtime
mutex for the duration of every FFI call, so blocking would stall all other
calls (including the close needed to cancel the wait). The callback model
matches the rest of the libmoq surface and follows the existing
terminal-callback lifetime contract (>0 live handle, 0 clean close, <0 error;
terminal fires even after an explicit close, and that's where user_data is
freed). moq_origin_consume_announced_close cancels a pending wait.

Scoped to libmoq (leaf crate, no in-workspace Rust dependents); the cbindgen
header regenerates with both functions. uniffi wrappers are unaffected.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 141e25d8-bbb9-40cf-bb7f-f8ad9762eede

📥 Commits

Reviewing files that changed from the base of the PR and between 7a70b12 and 825b61d.

📒 Files selected for processing (1)
  • rs/libmoq/README.md

Walkthrough

This PR adds an async "consume until announced" feature: Origin can register a wait task for a broadcast path, spawn a Tokio task that waits for the path announcement or cancellation, buffer the discovered broadcast, and invoke the caller-provided on_broadcast callback with a positive handle then a terminal code. It adds slab-backed task tracking, FFI wrappers moq_origin_consume_announced / moq_origin_consume_announced_close, integration tests for normal and cancelled flows, and README updates (including a change from moq_consume_frame_chunk to moq_consume_frame).

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a new API function to wait for broadcast announcements instead of polling.
Description check ✅ Passed The description is well-detailed and directly related to the changeset, explaining the problem, solution, design rationale, and test coverage.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/jolly-babbage-4683ed

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 and usage tips.

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

Actionable comments posted: 1

🤖 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/libmoq/README.md`:
- Around line 36-37: Update the C API list in the README so the documented
function names match the exported symbols: replace the stale
moq_consume_frame_chunk entry with moq_consume_frame (the symbol exported from
src/api.rs) and verify the nearby framed-function entry (e.g.,
moq_origin_consume_announced and moq_origin_consume_announced_close) is
spelled/named exactly as in the code; ensure the README uses the exact function
names moq_consume_frame, moq_origin_consume_announced, and
moq_origin_consume_announced_close so they match the Rust exports.
🪄 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

Run ID: db4bf4ed-ed28-47b9-8c19-e6cc0938c2ff

📥 Commits

Reviewing files that changed from the base of the PR and between 1982dd4 and 7a70b12.

📒 Files selected for processing (4)
  • rs/libmoq/README.md
  • rs/libmoq/src/api.rs
  • rs/libmoq/src/origin.rs
  • rs/libmoq/src/test.rs

Comment thread rs/libmoq/README.md
The C API list documented moq_consume_frame_chunk(frame, index, dst), but
api.rs exports moq_consume_frame(frame, dst). Correct the name and signature.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@kixelated kixelated merged commit ad71591 into main May 30, 2026
1 check passed
@kixelated kixelated deleted the claude/jolly-babbage-4683ed branch May 30, 2026 15:21
@moq-bot moq-bot Bot mentioned this pull request May 30, 2026
kixelated added a commit that referenced this pull request May 30, 2026
Reconcile main into dev. Key conflict resolutions:

- conducer crate renamed to kio (main #1547): applied across all of dev's
  newer code; dropped the stale conducer path-dep, kept dev's new flate2 dep.
- moq-mux: kept dev's thiserror Result (#1495); dropped main's CatalogSource
  as dead code since dev's catalog::Consumer already unifies Hang/MSF.
- moq-net: kept dev's OriginConsumer/AnnounceConsumer split (#1434) and the
  TrackConsumer end_at cap; kept dev's non-optional auto-created origins on the
  lite session/publisher (#e770).
- stats: combined main's StatsConfig + liveness retention (#1537, #1548) with
  dev's AnnounceConsumer usage.
- libmoq + moq-native: kept main's auto-reconnect (#1544), terminal-callback
  contract (#1546), and consume_announced (#1552), adapted to dev's
  AnnounceConsumer and OriginProducer connect API. Restored the InitFailed
  error variant and made moq-rtc handle the now-fallible Log::init.

cargo check/clippy/test all pass on the merged workspace.
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