Repository navigation
quest: plan follow-ups from the ffi and broadcast-epoch PRs #5151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
87ed38d
b6f5267
eccedd8
a7155b1
c9820ea
65bc9ef
63e3ac4
b19d7e9
9dd0f2d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # [S] A cancelled moq-ffi accept never takes a session | ||
|
|
||
| ## Goal | ||
|
|
||
| Cancelling a pending `MoqServer::accept` in any binding never takes an | ||
| incoming session: the next `accept` gets it. `MoqServer::cancel` still | ||
| releases the bound port, and every server call then resolves `Cancelled`. | ||
|
|
||
| ## Plan | ||
|
|
||
| Found in #5140 (ffi-cancel-read), decided 2026-10-09. Start after #5140 | ||
| lands: on `main` today `Task::run` still spawns every call and there is no | ||
| `Task::spawn`. That PR makes `Task::run` await in place, so a cancelled | ||
| future that is never polled again makes no progress. `MoqServer::listen` and `accept` keep the spawned path | ||
| (`Task::spawn`) because `MoqServer::cancel` blocks its thread until the | ||
| in-flight call finishes, and an `accept` parked on that same thread would | ||
| never finish (`server_cancel_releases_the_bound_port` hangs). So an `accept` | ||
| that is cancelled but not yet freed (uniffi frees it later, at | ||
| `rust_future_free`) can still take a session that then goes nowhere. | ||
|
|
||
| - Decided: close the listener through a handle kept outside the `Task` lock, | ||
| so `cancel` stops it without waiting on the in-flight call. Then `listen` | ||
| and `accept` use `run` like every other call, and `Task::spawn` goes away. | ||
| Rejected: accepting the race and documenting it. | ||
| - Regression in moq-ffi: poll an `accept` once and stop without freeing it, | ||
| connect a client, free the cancelled accept, and require the next `accept` | ||
| to return that session. Keep `server_cancel_releases_the_bound_port` | ||
| passing. | ||
|
|
||
| Public API: none. Wire: none. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -76,4 +76,5 @@ runs `just test interop --all`. | |
| - [Named error fields](/quest/m1/ffi-shape/error-fields.md) - `MoqError` variants name their fields, so no binding exposes a positional `v1` | ||
| - [Bindings](/quest/m0/broadcast-epoch/bindings.md) - the wrappers expose epochs and rename `session.epoch()`, on the reshaped wrappers | ||
| - [Group request demand](/quest/m1/ffi-shape/group-request-demand.md) - `MoqGroupRequest::demand()` in moq-ffi and every wrapper | ||
| - [Track request demand](/quest/m1/ffi-shape/track-request-demand.md) - `MoqTrackRequest::demand()` in moq-ffi and every wrapper, after Bindings | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Adding this child without updating the adjacent Group request demand plan leaves the two quests circular: AGENTS.md reference: AGENTS.md:L28-L28 Useful? React with 👍 / 👎.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The cycle is only on paper: #5139 implements the group quest with its own (Written by Claude Opus 5.5) |
||
| - [Layers guide](/quest/m1/ffi-shape/layers-guide.md) - a `doc/lib` page maps each Rust layer to every binding's module, once Codecs adds `audio` and `video` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # [S] A track request reports its demand | ||
|
|
||
| ## Goal | ||
|
|
||
| `MoqTrackRequest` gains `demand()` in moq-ffi and every wrapper (Python, Go, | ||
| Swift, Kotlin, Dart, C++), returning a `MoqTrackDemand` like | ||
|
Comment on lines
+5
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Expand the quest beyond the listed wrappers: adding AGENTS.md reference: AGENTS.md:L100-L102 Useful? React with 👍 / 👎.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed: (Written by Claude Opus 5.5) |
||
| `MoqTrackProducer.demand()`, so a dynamic track server can see when nobody | ||
| still wants the track and stop producing it. Mirrors Rust's | ||
| `track::Request::demand`. | ||
|
|
||
| ## Plan | ||
|
|
||
| Found in #5139 (group request demand), decided 2026-10-09: that quest | ||
| assumed `MoqTrackRequest.demand()` already existed, but moq-ffi only has | ||
| `demand()` on `MoqTrackProducer` and the media and JSON producers. Start | ||
| after #5139 lands, and follow its `MoqGroupRequest.demand()` binding shape, | ||
| but keep Rust's lifetime: `accept` hands the same track state to the | ||
| producer, so the handle keeps watching it and returns `Closed` only once the | ||
| request is rejected or the track closes. A dynamic server can then stop | ||
| producing when the last subscriber leaves. | ||
|
|
||
| Per the cross-package table, `rs/moq-c` gains the same on its | ||
| `moq_track_request_*` functions (following `moq_publish_media_demand`), and | ||
| the `doc/lib` pages list it. | ||
|
|
||
| Additive in every binding. It edits the same wrappers as | ||
| [Bindings](/quest/m0/broadcast-epoch/bindings.md) (#5146), so land it after | ||
| that PR to avoid conflicts, without blocking on it. Run | ||
| `just test interop --all`. Wire: none. | ||
|
|
||
| ## Related | ||
|
|
||
| - [Bindings](/quest/m0/broadcast-epoch/bindings.md) - edits the same wrappers; land after it | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # [XS] moq-cli import finishes its catalog producer | ||
|
|
||
| ## Goal | ||
|
|
||
| No moq-cli import path drops a catalog `track::Producer` without `finish()` | ||
| or `abort()`. The warning seen in about 1 of 7 loaded runs of | ||
| `import_delivers_the_catalog_finish_at_eof` is traced to its producer and | ||
| fixed, or shown harmless and the warning's cause removed. | ||
|
|
||
| ## Plan | ||
|
|
||
| Found in #5155, decided 2026-10-09: under load the test sometimes logs | ||
| `track::Producer dropped without finish() or abort() track=catalog.json`, | ||
| while the subscriber still sees a clean catalog finish. So some second | ||
| catalog producer, or a clone, is dropped on a path that skips `finish()`. | ||
| Find which one and finish or abort it at its source. | ||
|
|
||
| Public API: none. Wire: none. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # [S] TS passthrough jump test holds under load | ||
|
|
||
| ## Goal | ||
|
|
||
| `publish::tests::ts_passthrough_crosses_a_relay_through_a_flagged_jump` | ||
| (`rs/moq-cli`) passes under a loaded `just check`, fixed at its cause. | ||
|
|
||
| ## Plan | ||
|
|
||
| Seen 2026-10-09 by three PRs on unmodified `main` (#5146, #5155, #5153): the | ||
| assertion "moq-transport-14: both copies crossed" fails, so the recording | ||
| held at most one copy of the fixture. It failed 2 of 3 loaded runs and | ||
| passes alone. The test came in with #5003. It paces its input with a 15 ms | ||
| wall-clock sleep and waits up to 10 s. | ||
|
|
||
| Decided 2026-10-09: find why the second copy goes missing under load before | ||
| changing anything, then replace the wall-clock pacing with mocked time or | ||
| observable events where the fixture allows. Never widen the wait or add a | ||
| retry, per this questline's rules. | ||
|
|
||
| Public API: none. Wire: none. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # [S] @moq/watch follows the route that serves its path | ||
|
|
||
| ## Goal | ||
|
|
||
| When the exact route for a path ends while a covering prefix (such as | ||
| `pool`) still serves it, `@moq/watch` moves to the prefix instead of going | ||
| offline, as Rust's `moq play` does through the shared follow helper. | ||
|
|
||
| ## Plan | ||
|
|
||
| Found in #5154 (broadcast-epoch apps), decided 2026-10-09: | ||
| `Broadcast.#runBroadcast` in `js/watch` ignores `End`, so the player goes | ||
| offline even though a covering prefix still announces the path. Start after | ||
| #5154 lands, since it adds the helper this quest uses. | ||
|
|
||
| - Decided: use the shared follow helper. #5154 moves it from | ||
| `moq_mux::Source::follow` into moq-net (`origin::Consumer::follow`) and | ||
| mirrors it in `@moq/net`, per the cross-package table; this quest wires | ||
| `@moq/watch`'s `Broadcast` onto the JS one. The serving route is the most | ||
| specific one covering the path; another route taking over is a `Restart`, | ||
| or an `Update` when both carry the same epoch; routes beneath the path are | ||
| ignored. Rejected: a private copy in `@moq/watch`, and keeping the Rust | ||
| helper in moq-mux (maintainer, 2026-10-09: a net-layer concern that should | ||
| mirror across languages). | ||
| - Test: a path served both exactly and by a `pool` prefix; ending the exact | ||
| route moves playback to the prefix as a restart, and ending both goes | ||
| offline. | ||
|
|
||
| Public API: none. Wire: none. |
Uh oh!
There was an error while loading. Please reload this page.