Skip to content

feat(ffi): advertise JSON tracks in the catalog, add binary data tracks - #4137

Merged
kixelated merged 3 commits into
moq-dev:mainfrom
bgreenway:moq-ffi-data-track-catalog
Sep 25, 2026
Merged

kixelated merged 3 commits into
moq-dev:mainfrom
bgreenway:moq-ffi-data-track-catalog

Conversation

@bgreenway

Copy link
Copy Markdown
Contributor

Problem

The moq-ffi half of #4073. MoqBroadcastProducer::publish_json_snapshot / publish_json_stream create a bare track, and their docs (and the Python wrapper's) say to advertise it with set_catalog_section. That call refuses json, a reserved root section, so an FFI publisher (Python, Kotlin, Swift, Go, Dart) cannot make a JSON track discoverable from the catalog. There is also no FFI surface for binary data tracks, though moq_mux::binary exists.

Approach

The same routing as #4073, through the broadcast's catalog producer:

  • publish_json_snapshot / publish_json_stream now use catalog::Producer::json_snapshot / json_stream. The entry json.tracks.<name> (mode, and compression when set) is written on create and retired on finish or failure. The snapshot keeps its delta_ratio through json::Config::with_delta_ratio from feat(libmoq): advertise JSON tracks in the catalog, add binary data tracks #4073.
  • New publish_binary_snapshot / publish_binary_stream with MoqBinaryConfig { compression, mime }, returning MoqBinarySnapshotProducer { update, finish } / MoqBinaryStreamProducer { append, finish }.
  • moq_mux::json::Snapshot / Stream gain demand(), so the FFI JSON producers keep their existing demand() getter.

Impact

  • moq-ffi: JSON snapshot/stream tracks now appear in the catalog. A name the catalog already carries is refused instead of silently coexisting. Method signatures are unchanged.
  • moq-ffi: new MoqBinaryConfig record, two MoqBroadcastProducer methods and two producer objects. All additive.
  • moq-mux: json::Snapshot::demand / json::Stream::demand (additive).
  • Python wrapper: docstrings no longer point at set_catalog_section.
  • Tests: three new moq-ffi tests: JSON entries advertised and retired, binary entries with mode and mime, duplicate names refused. cargo clippy is clean; moq-ffi (154) and moq-mux (826) pass.

Alternatives

Same as #4073. Letting set_catalog_section write json / binary would bypass the typed entry and its retire-on-finish lifecycle. An opt-in flag would leave the documented path broken for every existing caller.

Follow-ups

  • Dart bindings: dart/moq_ffi/lib/src/moq.dart is generated and committed, and I can't run uniffi_bindgen_dart locally. I'll take the regenerated file from this PR's just dart check and push it here before marking the PR ready.
  • The Go and Python wrappers expose JSON only. Binary producers for them would be a small wrapper-only PR if wanted.

Brad Greenway added 3 commits September 25, 2026 07:41
The moq-ffi mirror of moq-dev#4073. publish_json_snapshot / publish_json_stream now
go through the broadcast's moq-mux catalog, so the catalog carries
json.tracks.<name> (mode, and compression when set) for as long as the
track lives and retires it on finish. New publish_binary_snapshot /
publish_binary_stream expose moq-mux's binary data tracks with an optional
mime. A name the catalog already carries is refused.

moq-mux's json Snapshot/Stream gain demand() so the FFI producers keep
their existing demand() getter.
@kixelated
kixelated marked this pull request as ready for review September 25, 2026 13:32
@coderabbitai

coderabbitai Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

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: ed84ccac-758b-4755-92da-6663aa45135a

📥 Commits

Reviewing files that changed from the base of the PR and between f822924 and be8dcaf.

📒 Files selected for processing (7)
  • dart/moq_ffi/lib/src/moq.dart
  • py/moq-rs/moq/publish.py
  • rs/moq-ffi/src/binary.rs
  • rs/moq-ffi/src/json.rs
  • rs/moq-ffi/src/lib.rs
  • rs/moq-ffi/src/test.rs
  • rs/moq-mux/src/json.rs

Included review availability: Your plan provides up to 4 included reviews per hour; 0 remain after this review.


Walkthrough

The Rust FFI now publishes catalog-backed binary snapshot and stream tracks. The Dart FFI exposes configuration and producer APIs for these tracks. JSON publishers now register tracks in the catalog, and mux JSON producers expose subscriber-demand handles. Tests cover catalog metadata, track removal, closed producers, and name conflicts. Python docstrings now describe JSON catalog behavior.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to be8dc

No concrete issue remains that blocks merging. Dart checksum agreement has not been independently verified.

Security Architecture Review

Security architecture risk: 🔵 Low · up to be8dc

The new publishing paths remain tied to the caller’s broadcast, and no new security bypass was established. Catalog and track creation are separate steps, however, and authorization outside these libraries and some failure-path behavior remain unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — Within the examined APIs, a caller able to publish can affect track payloads and discoverability on its held broadcast. No route to another broadcast is shown; upstream publisher authorization and downstream consumer exposure were not established.

Trust Boundaries and Controls

  • observed — Named data entries go through catalog reservation rather than the separate arbitrary-section setter, and FFI creation calls are serialized on the broadcast producer state.

Resilience and Maintainability Implications

  • inferred — Serialization and rendition cleanup support single-owner lifecycle behavior, but they do not make track creation and catalog registration one atomic externally visible transition.

Hardening Proposals

  • proposed — Consider verifying that catalog rejection cannot briefly satisfy a pending direct-track request, or ordering name acquisition before track publication if that outcome matters to consumers.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the catalog-backed JSON publishing changes, new binary track APIs, tests, and follow-up work. It is directly related to the changeset.
Title check ✅ Passed The title concisely identifies both primary changes: advertising JSON tracks in the catalog and adding binary data tracks.
Docstring Coverage ✅ Passed Docstring coverage is 95.65% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 23 functions across 6 files. (1 skipped: 1 …
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.
✨ Finishing Touches
✨ Simplify code
  • Create a new PR

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

Copy link
Copy Markdown
Collaborator

Verdict: MERGE

Positive fix for a real FFI gap: publish_json_* documented advertising via set_catalog_section, but that path refuses the reserved json root, so catalog discovery was impossible from Python/Dart/etc. Routing through catalog::Producer::json_snapshot / json_stream (same shape as #4073) is the right fix—typed entries, retire-on-finish, and duplicate-name refusal instead of silent coexistence.

The new binary snapshot/stream surface is a thin, additive mirror of moq_mux::binary with sensible config (compression, mime) and matching catalog lifecycle. Tests cover advertise/retire, mime/mode, and name collision. demand() on mux JSON producers keeps the existing FFI getter. Dart regen and Python docstring cleanup are appropriate.

Complexity is justified; bypassing via set_catalog_section or an opt-in flag would leave the documented path broken. Deferring Go/Python binary wrappers is fine as a follow-up.

This is an automated review, not the maintainer's decision
(Written by Grok)

@kixelated
kixelated merged commit e173ddd into moq-dev:main Sep 25, 2026
20 checks passed

Copy link
Copy Markdown
Collaborator

Squash-merged onto main as e173ddd. Check and Test were green, and the branch merged cleanly with current main, so json::Config::delta_ratio stays. Follow-up still open: Go and Python binary wrappers.

(Written by Grok 4.7)

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.

2 participants