moq-net: add per-track cache age (SUBSCRIBE_OK), reconcile draft field order, port timescale to js/net#1585
Merged
Merged
Conversation
Replace the hard-coded 5s group-eviction window in TrackProducer with a publisher-controlled `Track.cache` duration (default 5s, via `with_cache`). The producer evicts old groups using this value, and each subscriber's `stale` window is clamped to it: a group can't be waited for longer than the publisher keeps it around. The cache age is announced in the lite-05 SUBSCRIBE_OK (Publisher Cache, varint milliseconds) so a relay re-serves with the same eviction window. On the wire it follows the existing compression and timescale fields. The struct field serializes into the hang catalog as integer milliseconds and is skipped when it equals the default, so existing catalogs are unchanged. Mirrored into js/net (Track.cache + SUBSCRIBE_OK wire) for parity. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…js/net Reorder the lite-05 SUBSCRIBE_OK trailing fields to match draft-lcurley-moq-lite-05: Timescale, Cache, Compression (the merged timescale impl had emitted Compression, Timescale). Port timescale negotiation to js/net so it stays wire-compatible with a timestamped (Rust) publisher: SubscribeOk gains a `timescale` field, and a group-stream reader consumes the per-frame zigzag-delta timestamp varint when the negotiated timescale is non-zero. js/net doesn't surface or produce per-frame timestamps yet (it reads media timestamps from the container payload), so publishers advertise timescale 0 and the decoded delta is read only to keep frame framing in sync. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Summary
Adds a publisher-controlled cache age to
Track(replacing the hard-coded 5s group-eviction window), announced in lite-05SUBSCRIBE_OKso relays re-serve with the same window; each subscriber'sstalewindow is clamped to it. Also reconciles theSUBSCRIBE_OKfield order with the draft and ports timescale negotiation to js/net so JS↔Rust lite-05 is wire-compatible again.Implements
Publisher Cachefrom the moq-lite-05 draft (moq-dev/drafts#23): "max age, in ms, of the oldest group the publisher will retain," analogous to HTTPCache-Control: max-age.Cache age
rs/moq-netmodel:MAX_GROUP_AGE→pub const DEFAULT_CACHE(5s). NewTrack.cache: Duration(default 5s,with_cache, manualDefault, serde as integer-ms skipping default).evict_expiredusesTrack.cache.staleclamped tocacheinTrackProducer::subscribe,TrackWeak::subscribe,TrackSubscriber::update.track.cache; subscriber stampsinfo.cacheonto the reconstructed localTrack.js/net: mirroredTrack.cache+SUBSCRIBE_OKwire field.SUBSCRIBE_OK field order (reconciled with the draft)
The draft orders the trailing fields
Timescale, Cache, Compression, but the merged timescale impl (#1439) emittedCompression, Timescale. Per the draft, both Rust and JS now encode/decodeTimescale, Cache, Compression. lite-05 is WIP/unreleased, so this additive + reorder needs no version bump.Timescale port to js/net
PR #1439 added per-frame timestamps to the Rust moq-net wire but never touched js/net, leaving JS↔Rust lite-05 wire-incompatible. This PR:
timescaleto the JSSUBSCRIBE_OK, andjs/net doesn't yet surface or produce per-frame moq-net timestamps (it reads media timestamps from the container payload), so JS publishers advertise
timescale = 0and the decoded delta is read only to stay in sync. Fully surfacing/producing per-frame timestamps in JS (the js/hang container migration that Rust did across moq-mux) is a separate follow-up.Open items for the draft author
Duration Delta: draft PR Loop disk source #23 adds bothTimestamp DeltaandDuration Deltato FRAME, but the merged Rust impl (Add per-track timescale and frame timestamps to moq-lite #1439) only implementsTimestamp Delta. This PR matches the shipped Rust wire (timestamp-delta only). The draft should either dropDuration Deltaor it should be implemented in Rust first.Test plan
cargo test -p moq-net(350 pass) incl.cache_age_controls_eviction,stale_clamped_to_cache,cache_roundtrips_on_lite05,cache_absent_before_lite05cargo test -p hang(catalog round-trips unaffected;cacheskipped at default)just rs check(clippy-D warnings+ rustfmt)just js check+ biome;bun testin js/net (149 pass) incl. updated SUBSCRIBE_OK round-trip (timescale + cache + compression) and integration tests🤖 Generated with Claude Code
(Written by Claude)