diff --git a/quest/m1/README.md b/quest/m1/README.md index b97087b518..4c8268b8a3 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -70,6 +70,7 @@ transport, benchmark tooling); worktrees isolate commits, not semantics. - [BBR idle burst](/quest/m1/bbr-idle-burst.md) - a BBRv3 burst after a long idle paces near the learned bandwidth, proven by a fork regression - [P2P](/quest/m1/p2p/README.md) - opted-in clients serve each other over data channels and iroh while the relay stays the rendezvous and the fallback, under application policy - [One port](/quest/m1/one-port/README.md) - a relay speaks QUIC, STUN, WebRTC media, and SRT on one UDP port and HTTP, RTMP, and RTMPS on one TCP port +- [Signed priority](/quest/m1/signed-priority.md) - on dev, every API priority is an `i8` with 0 as the unset midpoint, and hang's built-ins sit above it - [Scope track priority](/quest/m1/track-priority-scope.md) - priority orders one owner's streams, and a shared cluster session is fair across tenants - [Stream sessions](/quest/m1/uring-tcp/README.md) - serve WebSocket and HTTP from the io_uring workers, where io_uring pays off most - [IETF on the ring](/quest/m1/uring-ietf.md) - the io_uring workers serve moq-transport sessions too, so a uring relay drops no client protocol diff --git a/quest/m1/signed-priority.md b/quest/m1/signed-priority.md new file mode 100644 index 0000000000..12ea0eb5ee --- /dev/null +++ b/quest/m1/signed-priority.md @@ -0,0 +1,44 @@ +# [L] Signed priority + +## Goal + +Every priority in the API is an `i8`, higher first, with 0 as the unset +midpoint: `track::Info`, `Subscription`, and `group::Fetch` in Rust, their +JS counterparts, moq-ffi, libmoq, and every wrapper. Nobody has to know that +127 is the middle of a `u8`, the default the moxygen line ships. The wire +stays a byte. + +## Plan + +Decided with the maintainer: + +- moq-lite carries `p + 128` (flip the top bit). The mapping is one-to-one + and keeps order, so a given byte means what it means today; only the API + number changes. The default becomes byte 128. +- IETF carries `128 - p`, saturating. An unset priority goes out as the + draft's usual 128, and an absent IETF priority decodes to 0. The cost is + that i8 -128 and -127 share byte 255, and IETF bytes 0 and 1 both decode to + 127. Pin both ends in tests. +- hang's built-in priorities move above 0, so hang media outranks a track that + never set one. Something like catalog 40, text 30, audio 20, video 10; the + spacing is the implementer's call. Rust and JS keep matching values. +- A zeroed libmoq `moq_track_info` then means the default, which retires the + need for a `priority_present` flag. + +Changing published `u8` fields to `i8` is an API break in every language, so +this lands on `dev`. Look for anything that does arithmetic on priority +(the lite send queue, JS send-order packing, the bandwidth allocator, the +relay's max-of-subscribers) and keep its ordering, not just its type. + +moq-archive's `Info::priority` follows. Its version-1 `.info` stores the +`u8`, so existing recordings must keep their meaning: store the moq-lite byte +(`p + 128`) or bump the format version, never reinterpret silently. +`doc/concept/moq-lite.md` (the 0..255 knob) and `doc/concept/standard.md` +(IETF 128 maps to 127) move to the new range and mapping. + +Report the wire impact in the PR: none in format, but the default byte on +moq-lite moves again. + +## Related + +- [Scope track priority](/quest/m1/track-priority-scope.md) - which streams a priority competes with, not its type