Skip to content

Commit 5510ab2

Browse files
kixelatedclaude
andcommitted
moq-lite-05: rename Max Latency to Stale (subscriber) and Cache (publisher)
The previous `Publisher Max Latency` and `Subscriber Max Latency` fields suggested a symmetric expiration rule, but they actually serve different roles: - `Publisher Cache` is a minimum retention guarantee. Groups may live longer than `Publisher Cache` and remain FETCH-able; the publisher just doesn't promise it. - `Subscriber Stale` is the subscriber's delivery preference for dropping non-latest groups from live streams. It does not imply the publisher discards them. Also clarified the Expiration section to make the asymmetry explicit: expiration applies only to live-stream delivery; cache retention is a separate concern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6023250 commit 5510ab2

1 file changed

Lines changed: 28 additions & 20 deletions

File tree

draft-lcurley-moq-lite.md

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ A subscription starts at a configurable Group (defaulting to the latest) and con
117117
The subscriber and publisher both indicate their delivery preference:
118118
- `Priority` indicates if Track A should be transmitted instead of Track B.
119119
- `Ordered` indicates if the Groups within a Track should be transmitted in order.
120-
- `Max Latency` indicates the maximum duration before a Group is abandoned.
120+
- `Stale` (subscriber) indicates the maximum age before a non-latest Group is dropped from live delivery; `Cache` (publisher) indicates the minimum retention guarantee for FETCH and reconnects.
121121

122122
The combination of these preferences enables the most important content to arrive during network degradation while still respecting encoding dependencies.
123123

@@ -387,19 +387,20 @@ An application MUST support gaps and out-of-order delivery even when `ordered` i
387387

388388

389389
## Expiration
390-
The Publisher and Subscriber both transmit a `Max Latency` value, indicating the maximum duration before a group is expired.
390+
Expiration governs when an older group is dropped from a live subscription's Group Stream(s).
391+
It is distinct from the publisher's retention guarantee (see `Publisher Cache` in [SUBSCRIBE_OK](#subscribe-ok)), which controls whether older groups remain available for FETCH or future subscriptions.
391392

392393
It is not crucial to aggressively expire groups thanks to [prioritization](#prioritization).
393394
However, a lower priority group will still consume RAM, bandwidth, and potentially flow control.
394395
It is RECOMMENDED that an application set conservative limits and only resort to expiration when data is absolutely no longer needed.
395396

396-
A subscriber SHOULD expire groups based on the `Subscriber Max Latency` in SUBSCRIBE/SUBSCRIBE_UPDATE.
397-
A publisher SHOULD expire groups based on the `Publisher Max Latency` in SUBSCRIBE_OK.
398-
An implementation MAY use the minimum of both when determining when to expire a group.
397+
The publisher SHOULD reset Group Streams for non-latest groups whose age relative to the latest group exceeds the `Subscriber Stale` value in SUBSCRIBE/SUBSCRIBE_UPDATE.
398+
The subscriber MAY also locally drop such groups for its own resource accounting.
399+
Expiration only removes the group from the live subscription's stream; if the group's age is still within `Publisher Cache`, the publisher SHOULD retain it for FETCH or new subscriptions.
399400

400401
Group age is computed relative to the latest group by sequence number.
401402
A group is never expired until at least the next group (by sequence number) has been received or queued.
402-
Once a newer group exists, a group is considered expired if the time between its first frame and the latest group's first frame exceeds `Max Latency`.
403+
Once a newer group exists, a group is considered expired if the time between its first frame and the latest group's first frame exceeds `Subscriber Stale`.
403404

404405
If the Track's negotiated `Timescale` is non-zero, the time delta is computed from per-frame timestamps (see [Frame](#frame)).
405406
Otherwise the delta is computed from wall-clock arrival time: the first byte of a group received (subscriber) or queued (publisher).
@@ -606,7 +607,7 @@ SUBSCRIBE Message {
606607
Track Name (s)
607608
Subscriber Priority (8)
608609
Subscriber Ordered (8)
609-
Subscriber Max Latency (i)
610+
Subscriber Stale (i)
610611
Start Group (i)
611612
End Group (i)
612613
}
@@ -626,9 +627,12 @@ A single byte representing whether groups are transmitted in ascending (0x1) or
626627
The publisher SHOULD transmit *older* groups first during congestion if true.
627628
See the [Prioritization](#prioritization) section for more information.
628629

629-
**Subscriber Max Latency**:
630-
This value is encoded in milliseconds and represents the maximum age of a group relative to the latest group.
631-
The publisher SHOULD reset old group streams when the difference in arrival time between the group and the latest group exceeds this duration.
630+
**Subscriber Stale**:
631+
The subscriber's preference, in milliseconds, for how long a non-latest group may remain in flight before being considered stale and dropped from live delivery.
632+
The publisher SHOULD reset (at the QUIC level) Group Streams for groups whose age relative to the latest group exceeds this duration.
633+
Applies only to non-latest groups; the latest group is never dropped on staleness grounds.
634+
A value of `0` means the subscriber wants only the latest group in live delivery (older groups are immediately stale once a newer group arrives).
635+
This is a delivery-time preference, not a retention rule: the publisher's cache (see `Publisher Cache` in [SUBSCRIBE_OK](#subscribe-ok)) may still hold these groups for FETCH or future subscriptions.
632636
See the [Expiration](#expiration) section for more information.
633637

634638
**Start Group**:
@@ -652,7 +656,7 @@ SUBSCRIBE_UPDATE Message {
652656
Message Length (i)
653657
Subscriber Priority (8)
654658
Subscriber Ordered (8)
655-
Subscriber Max Latency (i)
659+
Subscriber Stale (i)
656660
Start Group (i)
657661
End Group (i)
658662
}
@@ -672,11 +676,10 @@ SUBSCRIBE_OK Message {
672676
Message Length (i)
673677
Publisher Priority (8)
674678
Publisher Ordered (8)
675-
Publisher Max Latency (i)
679+
Publisher Cache (i)
676680
Start Group (i)
677681
End Group (i)
678682
Publisher Timescale (i)
679-
Publisher Cache (i)
680683
Publisher Compression (i)
681684
}
682685
~~~
@@ -702,11 +705,15 @@ A non-zero value is fixed for the lifetime of the subscription and MUST NOT chan
702705
Common values include `1000` (milliseconds), `1000000` (microseconds), `48000` (audio sample rate), and `90000` (RTP video clock).
703706

704707
**Publisher Cache**:
705-
The maximum age, in milliseconds, of the oldest group the publisher is willing to retain for late-arriving or reconnecting subscribers.
706-
Analogous to HTTP `Cache-Control: max-age`.
707-
A value of `0` means no historical retention beyond what is required for in-flight delivery; only live groups are available.
708-
A non-zero value indicates that the publisher will keep groups for at least this many milliseconds past their arrival, allowing a subscriber to issue a SUBSCRIBE or FETCH with an older `Start Group` and still receive the data.
709-
The unit is milliseconds (independent of `Publisher Timescale`) for consistency with `Publisher Max Latency` and to avoid coupling cache retention to media time when timescale is unspecified.
708+
The minimum age, in milliseconds, the publisher guarantees to retain a group past the arrival of a newer group.
709+
Applies only to non-latest groups; the latest group is always retained.
710+
Analogous to HTTP `Cache-Control: max-age` as a lower bound:
711+
712+
- A subscriber MAY issue a SUBSCRIBE or FETCH with an older `Start Group` and expect the publisher to still have it, as long as the group's age does not exceed `Publisher Cache`.
713+
- The publisher MAY retain groups longer than `Publisher Cache` (a best-effort cache beyond the guarantee); subscribers MUST NOT assume older groups are unavailable.
714+
715+
A value of `0` means no retention guarantee beyond live delivery; older groups MAY still be available but the publisher makes no promise.
716+
The unit is milliseconds (independent of `Publisher Timescale`) so cache retention is decoupled from media time when timescale is unspecified.
710717
The value MAY change in subsequent SUBSCRIBE_OK messages to reflect changing publisher policy; the subscriber SHOULD use the most recent value.
711718

712719
**Publisher Compression**:
@@ -895,7 +902,8 @@ A generic library or relay MUST NOT inspect or modify the decompressed contents
895902
- Added `Publisher Timescale` to SUBSCRIBE_OK for per-track timestamp negotiation. When `Publisher Timescale` is 0, the per-frame timestamp/duration fields are omitted entirely from FRAME and datagram bodies.
896903
- Added `Timestamp Delta` and `Duration Delta` to FRAME, both zigzag-encoded signed varints (present only when timescale is non-zero). `Duration Delta = 0` is the common "unchanged" case and fits in one byte; a resolved duration of `0` means "until the next frame".
897904
- Added `Timestamp` and `Duration` to the QUIC datagram body (absolute, present only when timescale is non-zero).
898-
- Added `Publisher Cache` to SUBSCRIBE_OK, expressing maximum group retention for late or reconnecting subscribers (milliseconds, similar to HTTP `Cache-Control: max-age`).
905+
- Renamed `Publisher Max Latency` to `Publisher Cache` in SUBSCRIBE_OK, now defined as a minimum retention guarantee (similar to HTTP `Cache-Control: max-age`). Groups may live longer than `Publisher Cache` and remain FETCH-able.
906+
- Renamed `Subscriber Max Latency` to `Subscriber Stale` in SUBSCRIBE/SUBSCRIBE_UPDATE. It is the subscriber's delivery-time preference for dropping non-latest stale groups, separate from the publisher's retention guarantee.
899907
- Timestamp-based expiration replaces wall-clock arrival time when a Track timescale is negotiated.
900908
- Added QUIC datagram delivery for groups, sharing Subscribe IDs with existing subscriptions (no separate control stream).
901909
- Added `Publisher Compression` to SUBSCRIBE_OK for per-frame payload compression (`none` or `deflate`).
@@ -919,7 +927,7 @@ A generic library or relay MUST NOT inspect or modify the decompressed contents
919927
- Added PROBE stream replacing SESSION_UPDATE bitrate.
920928
- Removed ANNOUNCE_INIT message.
921929
- Added `Hops` to ANNOUNCE.
922-
- Added `Subscriber Max Latency` and `Subscriber Ordered` to SUBSCRIBE and SUBSCRIBE_UPDATE.
930+
- Added `Subscriber Stale` and `Subscriber Ordered` to SUBSCRIBE and SUBSCRIBE_UPDATE.
923931
- Added `Publisher Priority`, `Publisher Max Latency`, and `Publisher Ordered` to SUBSCRIBE_OK.
924932
- SUBSCRIBE_OK may be sent multiple times.
925933

0 commit comments

Comments
 (0)