Repository navigation
Conversation
moq play follows its path through a new moq_mux::Source::follow: it plays on Start, starts over with a fresh catalog, decoders, and clock on Restart, lets what is playing finish on End and waits for the next Start, and ignores Update. @moq/watch video skips the catch-up gate and both halves re-anchor the shared clock on a republished instance. demo/web stats resubscribes on a restart. Publishers and the lite announce logs name the epoch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`origin::Consumer::follow(path)` returns `announce::Follow`, which reduces the announcements of every route covering a path to the Start, Update, Restart, and End of the one serving it. `@moq/net` mirrors it as `Origin.Consumer.follow(path)` (and on `Producer` and `Table`), returning an `Announce.Consumer`. `routed` is now the follower's first event. `moq play` builds on it, and `moq_mux::Source::follow` / `moq_mux::Follow` are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`Broadcast` follows its name through `Origin.follow`, so the exact route ending while a covering prefix still serves the name moves playback to the prefix instead of going offline. A name outside the origin's scope is now a refusal (`status` "error") instead of an effect error logged to the console. `@moq/net`'s follower is a synchronous reducer inside the announced loop, so a followed stream delivers in step with an announced one. The async version delivered the initial start after a quick refusal, which re-requested and cleared it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # doc/lib/rs/moq-net.md # quest/m0/broadcast-epoch/README.md
…ev#5141) `quest check` fails on main: both blockers landed and their quests were deleted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A route claiming only paths beneath the followed one (a scoped dynamic at the same prefix) could win that prefix on cost and mask the route that serves the path, so a republish of the real one produced no restart. Scoping the follower to the literal path drops such routes, as requests already do. JS also falls back to the whole scope for a path no pattern can spell (a `*` in a segment), as Rust does, and an announced stream no longer closes when it reaches such a path: its captures are none, as in Rust. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The restart check read the catalog broadcast's instance, so a rendition reading another broadcast through a `broadcast` override missed that one's republish and froze, while a catalog-only republish reset the clock with the media unchanged. Key it on the resolved media's path and instance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Falling back to the whole scope for a path with a `*` segment lets a route that never serves it win its prefix, and JS announcements already stop at such a prefix. Refuse it instead (`Error::InvalidPath`, a throw in JS), as `routed` did before it was built on `follow`, and drop the partial JS captures guard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The replay a follower starts with names a covering prefix before the exact path beneath it, which came out as a start on the prefix and then a restart onto the exact path, so a late-joining player requested the broadcast twice. Fold every announcement on hand (one table change in JS) into one event. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… path Folding every change on hand into one event turned an end followed by a start under the same epoch into an update, which hid a gap that had already ended the request on the old route, so @moq/watch never asked again. Fold only while the path is unserved (the late-join replay), and pass each change through once something serves it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A covering route of one epoch arriving as the exact route goes, both before the follower is polled, reaches it as an update: the announce cursor delivers by prefix, so the path never shows unserved. A player whose broadcast had already ended ignored that update and stayed stopped. With nothing playing, an update now plays the path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…nto quest/m0/broadcast-epoch/moqsrc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
Author
|
Outcome: implementation complete. This PR stays a draft until its dependencies land.
(Written by Claude Opus 5.5) |
moqsrc holds its pads only when the source goes away. A catalog the live source lacks or refuses (NotFound, Unauthorized) posts the session error, as on main. Mid-stream, only malformed content counts against the source, since a producer going away surfaces as almost any error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…och/moqsrc Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # quest/m0/broadcast-epoch/README.md # quest/m0/broadcast-epoch/moqsrc.md
Contributor
Author
|
Closing as superseded by #5191, which landed the same moqsrc quest: following the path's announcements, pads kept by rendition across restarts, held pads on source loss, and a missing or refused catalog failing the session. The two follow-ups planned from this PR (moqsink's first catalog and moqsrc A/V alignment) are in #5189. The moq-net fix this PR found, a restarted prefix restarted twice on lite-06, landed separately in #5182. (Written by Claude Opus 5.5) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
moqsrcresolves its path once. Now that subscriptions are sticky (#5087), it keeps playing a replaced broadcast until that broadcast's route goes away, and then ends with EOS or a session error. A restarted publisher, a newer instance taking over, or a lite-06 end and start never reaches the pipeline as a switch.Completes
quest/m0/broadcast-epoch/moqsrc.md.Approach
Follow announcements. The session follows its path with
origin::Consumer::followfrom feat(apps): players follow announce Start, Restart, and End #5154. AStartorRestartcancels the old run's pumps, then starts a run on the route serving the path. AnUpdatestarts one only when nothing is playing, meaning the path came back after a gap that the announcements folded away. AnEndholds the pads.Pads by rendition. A slot per rendition name holds the pad between pumps, so a restart or an in-run caps or container change hands the same pad to the next pump. The new pump pushes stream-start and its caps; refused caps fail as not negotiated. On its first buffer it pushes a segment whose base is the current running time, so a synced sink does not drop the new run as late. A rendition the catalog retires ends with EOS, and a new one gets a new pad.
Source loss holds. A track or catalog that ends or loses its source hands its pad back without EOS. This works whether the loss arrives before or after
End, and the nextStartresumes on the same pads. A catalog that the live source lacks or refuses (NotFound,Unauthorized) still posts the session error, as does a malformed one, and losing the connection still ends the session. Mid-stream only malformed content counts against the source, because a producer that goes away surfaces as almost any error, includingNotFoundfor a group that can never be served.Tests. Unit tests cover both orders of source loss and
End, a reshape keeping its pad, and a broadcast without a catalog failing the session withNotFound.tests/source.rsrunsmoqsrc ! fakesink sync=true max-lateness=20msagainst an in-process relay. It covers:Each case checks that the new run renders at its frame rate on one pad with no bus error. Pushing the segment with a base of zero fails all seven, and switching on every
Updatefails the update case.Impact
Alternatives
Follow-ups
a_restarted_prefix_switchesfound). feat(apps): players follow announce Start, Restart, and End #5154 (Follow) has landed and main is merged in. Main gets merged in again once fix(net): don't renew a prefix whose winner already restarted #5182 lands. If quest: plan moqsink's first catalog and moqsrc A/V alignment #5189 lands first, this PR also drops its two quests'Requiredlinks to the moqsrc quest it deletes.moqsinklists a pad only once its caps arrive. Planned in quest: plan moqsink's first catalog and moqsrc A/V alignment #5189 asquest/m1/gst-first-catalog.md:moqsinkreserves each pad's catalog slot when the pad is requested.quest/m1/gst-src-av-sync.md.(Written by Claude Opus 5.5)