feat(moq-hls): list a durable archive timeline without the live window - #4155
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A catalog archive entry with a store and no replay path declares its ranges durable on that broadcast, so the exporter lists everything the timeline retains and only its pops trim the playlists. DASH timeShiftBufferDepth becomes the listed span; --window still bounds live playlists and caps segment max-age. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Squash-merged onto A catalog Follow-ups, unchanged: the stock (Written by Grok 4.7) |
Completes the Archive HLS window quest.
moq-hlsnow lists a durable timeline's whole retained range instead of trimming it to--window, so a replayed recording no longer needs a server-wide--windowraised past its length (which also inflated segmentmax-ageand DASHtimeShiftBufferDepthfor every live broadcast on the server).Decision: the catalog
archiveentry says the timeline is authoritativeA broadcast's timeline is treated as authoritative when its catalog
archiveentry names astoreand noreplaypath. The draft already defines both: with a store every advertised range is durable, and withoutreplaythe timeline lives on the catalog's own broadcast. So those ranges stay FETCHable from this broadcast until the timeline pops them, and only those pops trim the playlists.Alternatives considered:
Broadcaster: puts the policy in every embedder and needs a side channel for the stockmoq export hlsserver to learn which broadcasts are recordings.The catalog signal needs no new field, no new API, and keeps the policy in the protocol's own declaration.
Derived values
timeShiftBufferDepth(and thesuggestedPresentationDelaybound) is the listed span for a durable timeline, and the configured window otherwise.Cache-Control: max-agestill comes from--window, so it stays capped for every broadcast.API and wire impact
export::Config::windowkeeps its type; its doc now says what it doesn't bound.archive.storeandarchive.replayfields.archiveentry has astoreand noreplaygets unbounded playlists. No publisher in this repo setsstoreyet; a replay's embedder sets it on the catalog it supplies.Tests
a_durable_timeline_lists_past_the_windowreplays 24s of recording under the default 16s window: the durable entry lists segment 0 withEXT-X-MEDIA-SEQUENCE:0andtimeShiftBufferDepth="PT24.000S", while a live-style entry and an entry with areplaypath keep the window. The existing DVR test now runs against a durable entry, so timeline pops still trim it.Notes
just checkpasses tests and lint for this diff but fails_publish-teston a pre-existing line issue from feat(cli): record and replay archives withexport archive/import archive#4113:rs/moq-cli/Cargo.tomlhasmoq-json = { workspace = true }as a dev-dependency of a published crate. Left for the line so this PR stays focused.moq import archivepublishes no live catalog group, so the stock server still needs an embedder to supply the replay's catalog (as the tests do). Stampingstoreon that catalog belongs with that follow-up.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code