You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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>
Copy file name to clipboardExpand all lines: draft-lcurley-moq-lite.md
+28-20Lines changed: 28 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -117,7 +117,7 @@ A subscription starts at a configurable Group (defaulting to the latest) and con
117
117
The subscriber and publisher both indicate their delivery preference:
118
118
- `Priority`indicates if Track A should be transmitted instead of Track B.
119
119
- `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.
121
121
122
122
The combination of these preferences enables the most important content to arrive during network degradation while still respecting encoding dependencies.
123
123
@@ -387,19 +387,20 @@ An application MUST support gaps and out-of-order delivery even when `ordered` i
387
387
388
388
389
389
## 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.
391
392
392
393
It is not crucial to aggressively expire groups thanks to [prioritization](#prioritization).
393
394
However, a lower priority group will still consume RAM, bandwidth, and potentially flow control.
394
395
It is RECOMMENDED that an application set conservative limits and only resort to expiration when data is absolutely no longer needed.
395
396
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.
399
400
400
401
Group age is computed relative to the latest group by sequence number.
401
402
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`.
403
404
404
405
If the Track's negotiated `Timescale` is non-zero, the time delta is computed from per-frame timestamps (see [Frame](#frame)).
405
406
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 {
606
607
Track Name (s)
607
608
Subscriber Priority (8)
608
609
Subscriber Ordered (8)
609
-
Subscriber Max Latency (i)
610
+
Subscriber Stale (i)
610
611
Start Group (i)
611
612
End Group (i)
612
613
}
@@ -626,9 +627,12 @@ A single byte representing whether groups are transmitted in ascending (0x1) or
626
627
The publisher SHOULD transmit *older* groups first during congestion if true.
627
628
See the [Prioritization](#prioritization) section for more information.
628
629
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.
632
636
See the [Expiration](#expiration) section for more information.
633
637
634
638
**Start Group**:
@@ -652,7 +656,7 @@ SUBSCRIBE_UPDATE Message {
652
656
Message Length (i)
653
657
Subscriber Priority (8)
654
658
Subscriber Ordered (8)
655
-
Subscriber Max Latency (i)
659
+
Subscriber Stale (i)
656
660
Start Group (i)
657
661
End Group (i)
658
662
}
@@ -672,11 +676,10 @@ SUBSCRIBE_OK Message {
672
676
Message Length (i)
673
677
Publisher Priority (8)
674
678
Publisher Ordered (8)
675
-
Publisher Max Latency (i)
679
+
Publisher Cache (i)
676
680
Start Group (i)
677
681
End Group (i)
678
682
Publisher Timescale (i)
679
-
Publisher Cache (i)
680
683
Publisher Compression (i)
681
684
}
682
685
~~~
@@ -702,11 +705,15 @@ A non-zero value is fixed for the lifetime of the subscription and MUST NOT chan
702
705
Common values include `1000` (milliseconds), `1000000` (microseconds), `48000` (audio sample rate), and `90000` (RTP video clock).
703
706
704
707
**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.
710
717
The value MAY change in subsequent SUBSCRIBE_OK messages to reflect changing publisher policy; the subscriber SHOULD use the most recent value.
711
718
712
719
**Publisher Compression**:
@@ -895,7 +902,8 @@ A generic library or relay MUST NOT inspect or modify the decompressed contents
895
902
- 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.
896
903
- 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".
897
904
- 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.
899
907
- Timestamp-based expiration replaces wall-clock arrival time when a Track timescale is negotiated.
900
908
- Added QUIC datagram delivery for groups, sharing Subscribe IDs with existing subscriptions (no separate control stream).
901
909
- 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
0 commit comments