Repository navigation
quest: plan export source pinning and the stitch catalog bound #5247
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
Merged
+84
−0
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # [S] An export's later requests stay on the broadcast it resolved | ||
|
|
||
| ## Goal | ||
|
|
||
| `moq_mux::Source` keeps the first `broadcast::Consumer` it resolves for each | ||
| path, its own and every cross-broadcast reference, and serves every later | ||
| request for that path from that handle. A late rendition subscribe or SI | ||
| repoint never lands on a replacement, epoch or not. On a replaced instance | ||
| it fails loudly instead of splicing the new publisher's data into the old | ||
| program. | ||
|
|
||
| ## Plan | ||
|
|
||
| Found by Codex on #5147 (2026-10-10), planned the same day. `Source` pins | ||
| its own path by epoch (`epoch` in `rs/moq-mux/src/source.rs`, set through | ||
| `pinned` from `ts::Export`). An epochless route (every default lite-06 | ||
| session) has `None`, so each later request re-resolves the path, and if a | ||
| replacement won in the meantime, it serves that request even without | ||
| `--stitch`. | ||
|
|
||
| - Decided: pin by handle, replacing the epoch field. One mechanism covers | ||
| epoch and epochless routes. A replaced instance's sticky front refuses new | ||
| tracks, so a late request on it errors, and the Follower decides what | ||
| happens next (`Replaced`, or a stitch). | ||
| - Decided: pin every resolved path, not only the source's own, so a replaced | ||
| sibling (`broadcast: ./source`) cannot splice in either. | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| - The pin lifecycle follows the export's instance. A stitch builds a new | ||
| `Source` whose own-path entry is seeded with the broadcast `follow` was | ||
| given (sibling entries start empty), so its first track request can't | ||
| resolve a newer replacement. A same-epoch return replaces the own-path | ||
| handle with the returned broadcast, since the old one's routes are gone. | ||
| - The guarantee starts at a path's first resolution. A sibling the catalog | ||
| first references after a replacement resolves whatever serves it then. | ||
| The export never held another instance of that path, so that isn't a | ||
| splice. | ||
| - Tests, with mocked time, on an epochless route: an export resolves `live`, | ||
| a replacement wins `live`, and then a rendition added to the old catalog | ||
| (and an SI repoint) fails rather than reading the replacement. The same | ||
| for a sibling reference already resolved. A stitch whose replacement is | ||
| itself replaced before the first track request still reads the broadcast | ||
| it followed. A same-epoch return reads the returned handle. Today's | ||
| epoch-pin test (`source.rs`) moves to the handle. | ||
|
|
||
| Public API: no signature change, but a behavior change. A `Source` reused | ||
| across a route replacement now returns its pinned handle for a path it | ||
| already resolved (`broadcast`, `catalog`, and track requests), or fails on | ||
| the replaced instance, instead of resolving the current route. Document it | ||
| on `Source`. Wire: none. | ||
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # [S] A TS export stitch is bounded by the linger until its catalog arrives | ||
|
|
||
| ## Goal | ||
|
|
||
| When `moq export ts --stitch` (or moq-srt egress with `stitch`) switches to | ||
| a replacement mid-stream, `--linger` bounds the wait for the replacement's | ||
| catalog, as it bounds a same-epoch return. A replacement that never delivers | ||
| its first catalog snapshot ends the export with an error instead of stalling | ||
| it with nothing going out. | ||
|
|
||
| ## Plan | ||
|
|
||
| Found while iterating #5147 (2026-10-10), planned the same day. `ts::Follower` | ||
| (`rs/moq-mux/src/container/ts/follower.rs`) carries a linger deadline for a | ||
| return, which #5147 extended to the returned catalog's first snapshot. A | ||
| stitch that starts after the old broadcast ended inherits that deadline. A | ||
| mid-stream stitch, taken from `Running` while the old instance still serves, | ||
| carries none (`settling: None` in `State::Following`), so its catalog wait is | ||
| unbounded. | ||
|
|
||
| - Decided: the linger is the one bound, from the `Restart` to the | ||
| replacement's first catalog snapshot. With `--linger 0` a stitch only | ||
| succeeds when the catalog is already there. Rejected: bounding by | ||
| `--delay`, and a fixed constant. | ||
| - On expiry the export ends with an error naming the replacement that never | ||
| served its catalog. | ||
| - Tests, with mocked time: a stitch onto a replacement whose catalog never | ||
| answers ends at the linger. One whose catalog answers within it switches | ||
| as today. | ||
| - Docs: the `--stitch` and `--linger` text in `doc/bin/cli.md` and | ||
| `doc/bin/srt.md`, including that the default `--linger 0s` lets a stitch | ||
| follow only a replacement whose catalog is already there. | ||
|
|
||
| Public API: none. Behavior: a stitch can now end the export. Wire: none. |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pinning every resolved path introduces per-export state that fans out across N sibling routes and is consulted by M later requests, but the plan only requires correctness tests. Add a benchmark sweeping both path count and request count so an implementation with table-wide lookup or cleanup costs cannot land without exposing the slope.
AGENTS.md reference: AGENTS.md:L36-L37
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disagree. The fan-out rule targets axes that grow with the table: publishers, subscribers, routes, sessions. This map is per export and keyed by path. Its N is the number of distinct broadcasts one catalog references (the own path plus, typically, zero to two siblings), and each request is one hash lookup. No request touches the whole map, and nothing is cleaned up across exports, so there is no slope to expose.
(Written by Claude Opus 5.5)