Skip to content

feat(net)!: remove the deprecated broadcast finish and abort - #4152

Open
kixelated wants to merge 11 commits into
devfrom
quest/m1/broadcast-close/remove
Open

kixelated wants to merge 11 commits into
devfrom
quest/m1/broadcast-close/remove

Conversation

@kixelated

@kixelated kixelated commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

The line #4031 made close() the one way to end a broadcast and deprecated the finished-versus-aborted split, which never survives a hop (a broadcast has no FIN on the wire). The deprecated APIs still need removing on dev, and closed() still carries an Error cause nobody can act on.

Depends on #4031 reaching main and then dev. This branch merges quest/m1/broadcast-close/README into dev so the deprecations exist to remove; until #4031 lands and main merges into dev, the diff here includes the line's commits (#4047, #4126). Kept as a draft until then.

Approach

  • moq-net: drop broadcast::Producer::finish, abort, Consumer::is_finished, and the finished/abort state they read. Consumer::closed(), Dynamic::closed(), and Dynamic::poll_closed now return ().
  • moq-ffi / libmoq: drop MoqBroadcastProducer::finish and moq_publish_finish.
  • Bindings: drop Python finish(), Swift finish(), Go Finish(); Dart regenerated.
  • JS: drop broadcast.Producer.close(abort) / Consumer.close(abort); closed narrows to GetPromise<null>.
  • Kotlin forced end (decision): Kotlin gets broadcast.end(), via a uniffi.toml rename of the generated close() (replacing the old exclude). Kotlin's close()/use {} is AutoCloseable and only releases the handle, which ends the broadcast once no dynamic() handle remains. Without finish(), a Kotlin app holding a dynamic() serving loop would have no way to end the broadcast short of cancelling that loop. A distinct name is the cheapest fix that keeps the Rust semantics; the quest's Plan records it.

Impact

  • Rust moq-net (breaking): broadcast::Producer::{finish, abort} and broadcast::Consumer::is_finished removed; broadcast::Consumer::closed() and broadcast::Dynamic::{closed, poll_closed} return () instead of Error.
  • moq-ffi (breaking): MoqBroadcastProducer.finish() removed from every binding. Kotlin gains MoqBroadcastProducer.end() (the forced end), since close() there is AutoCloseable.
  • libmoq C ABI (breaking): moq_publish_finish removed; use moq_publish_close.
  • Python BroadcastProducer.finish(), Swift BroadcastProducer.finish(), Go BroadcastProducer.Finish() removed.
  • @moq/net (breaking): broadcast.Producer.close(abort) and broadcast.Consumer.close(abort) lose the parameter; closed is GetPromise<null>.
  • moq-transcode: an idle rung whose source broadcast closes now aborts its output with Error::Dropped explicitly (it was always Dropped in practice).
  • Wire: none.

Alternatives

  • Kotlin with no forced end: document that every dynamic() handle must be closed too. Rejected: a serving loop blocked in requestedTrack() only returns once the broadcast ends, so the two wait on each other.
  • End the broadcast when the FFI producer handle drops, in every binding: makes Kotlin's close() a forced end, but changes drop semantics for Python, Swift, Go, and Dart apps that keep serving through dynamic() after releasing the producer.
  • Another Kotlin name (closeBroadcast(), shutdown()): end() is shortest and matches the docs' wording.

Testing

Rust nextest (4384 pass), JS, Python, Go, Dart, and Kotlin checks pass locally; Kotlin gains a test that end() ends a broadcast while a dynamic() handle is still open. Swift is uncompiled locally (Linux).

Follow-ups

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

kixelated and others added 11 commits September 24, 2026 10:28
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ose/README

# Conflicts:
#	doc/lib/rs/moq-net.md
#	js/net/src/origin.ts
#	rs/moq-net/src/model/broadcast.rs
#	rs/moq-net/src/model/origin.rs
…4127)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…se/remove

# Conflicts:
#	quest/m1/README.md
#	rs/moq-ffi/src/test.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

#4173 moves this quest out of the broadcast-close line to quest/m1/broadcast-remove.md (Required: the line), so #4031 can land on main first. When this PR merges its base, delete the quest at that new path and drop its entry from quest/m1/README.md.

(Written by Claude Opus 5.5)

@kixelated
kixelated marked this pull request as ready for review September 26, 2026 00:16
@chatgpt-codex-connector

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-09-26T00:20:58.297380Z 2a53e53 Draft marked ready
ℹ️ 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.

This branch has not been deployed

No deployments
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