From fd07b1ee8e6866c396aba157a1f484933cfb5692 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Fri, 25 Sep 2026 15:43:19 -0700 Subject: [PATCH] quest: dropped sources, video keyframe flag, interop flakes Co-Authored-By: Claude Opus 5.5 --- quest/m1/README.md | 3 +++ quest/m1/dropped-sources.md | 27 +++++++++++++++++++++++++++ quest/m1/interop-flakes.md | 23 +++++++++++++++++++++++ quest/m1/video-keyframe-flag.md | 24 ++++++++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 quest/m1/dropped-sources.md create mode 100644 quest/m1/interop-flakes.md create mode 100644 quest/m1/video-keyframe-flag.md diff --git a/quest/m1/README.md b/quest/m1/README.md index b9986833e0..9f5c9d652f 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -22,8 +22,10 @@ transport, benchmark tooling); worktrees isolate commits, not semantics. - [Announce compression](/quest/m1/announce-compression.md) - a lite-07 announce reuses the path head and hop-chain tail of a live announcement on its stream instead of resending them - [lite-07 count settle](/quest/m1/lite-count-settle.md) - moq-lite-07 subscribers stop waiting for a subscription's tail once SUBSCRIBE_END's stream count is reached - [Session death error](/quest/m1/session-death-error.md) - a dying session ends its tracks with its own error in Rust and JS, never a clean end, `Dropped`, or `Cancel` +- [Dropped sources](/quest/m1/dropped-sources.md) - consumers see the producer's real error on every end path, never `Dropped` - [JS bare FIN](/quest/m1/js-bare-fin.md) - a `@moq/net` subscriber aborts a track whose subscribe stream FINs before its declared end, like Rust - [Track tail interop](/quest/m1/track-tail-interop.md) - a Rust publisher ending a track with a group in flight is read to its end by the JS subscriber, and the reverse, in `just test interop` +- [Interop flakes](/quest/m1/interop-flakes.md) - the interop harness passes with other runs sharing the machine - [Signal.race cleanup](/quest/m1/signal-race.md) - `Signal.race` releases its signal listeners when its result loses a race - [Origin narrowing](/quest/m1/origin-narrowing.md) - a live origin grant narrows in place and ends the subscriptions it no longer covers, the deafen boundary #2714 asked for - [Auth expiry clock](/quest/m1/auth-expiry-clock.md) - moq-auth and the relay hold one fixed expiry deadline and honour the same skew allowance @@ -60,6 +62,7 @@ transport, benchmark tooling); worktrees isolate commits, not semantics. - [Transcode source](/quest/m1/transcode-source.md) - select a rendition the chosen backend can actually decode - [Egress rendition pick](/quest/m1/egress-rendition-pick.md) - WHEP and single-track RTMP/FLV serve the best rendition, not the first by name - [Keyframe trigger](/quest/m1/keyframe-trigger.md) - an application can ask the built-in capture encoder for a keyframe +- [Video keyframe flag](/quest/m1/video-keyframe-flag.md) - encoded video marks its keyframes, so a requested cut never forces an extra one after a cadence keyframe - [QoS](/quest/m1/qos/README.md) - broadcast health: relay starvation and timeliness histograms, and client stats broadcasts from publishers and viewers - [Drain](/quest/m1/drain/README.md) - relay restarts drain sessions over GOAWAY instead of hard-dropping them - [Transport upgrade](/quest/m1/transport-upgrade/README.md) - a session that came up over WebSocket moves to QUIC once the QUIC dial lands, handing over at a group boundary diff --git a/quest/m1/dropped-sources.md b/quest/m1/dropped-sources.md new file mode 100644 index 0000000000..9fc495174f --- /dev/null +++ b/quest/m1/dropped-sources.md @@ -0,0 +1,27 @@ +# [M] Consumers see the producer's real error, never Dropped + +## Goal + +A track or broadcast that ends because its source ended reports the source's +own error to every consumer, locally and across a relay. `Dropped` means only +that a handle was dropped without an end, which a correct producer never does. +#4179 fixed one path (a revoked upstream subscription now reads +`Unauthorized`); the rest still surface `Dropped`. + +## Plan + +- Known sources, from #4179: a source closing, a route leaving the origin's + table, and a withdrawn source broadcast. Find each place a consumer can + observe `Dropped` and make the ending side carry its real error (an explicit + `abort` or a preserved cause), at the source rather than by remapping at the + consumer. +- moq-transport: a `PUBLISH_DONE` carrying Unauthorized arrives as + `Error::Remote(1)`. Map it to the same error lite reports. +- Regression tests per path, each failing on `Dropped` today, in-process and + over a mock session. + +Public API: none expected; error values consumers observe change. Wire: none. + +## Related + +- [#4179](https://github.com/moq-dev/moq/pull/4179) - fixed the revoked-upstream path diff --git a/quest/m1/interop-flakes.md b/quest/m1/interop-flakes.md new file mode 100644 index 0000000000..679c0344cf --- /dev/null +++ b/quest/m1/interop-flakes.md @@ -0,0 +1,23 @@ +# [S] Interop harness runs clean in parallel + +## Goal + +`just test interop --all` passes reliably while other harness runs share the +machine. Two known flakes: concurrent Nix shells reserve the same port because +each keeps its reservations under its own `TMPDIR`, and the browser driver's +pause click is sometimes blocked by the canvas (`js -> js`). + +## Plan + +- Port reservations live under one root shared by every shell (not + `TMPDIR`), or ports come from the OS (bind to 0 and pass the result). Prefer + whichever removes the reservation file entirely. +- The pause control is driven in a way the canvas cannot intercept (an API or + keyboard path, or waiting for the element to be actionable), not a retry. +- Prove it by running two `--all` harnesses at once, several times. + +Public API: none. Wire: none. + +## Related + +- [#4181](https://github.com/moq-dev/moq/pull/4181) - where both flakes were seen diff --git a/quest/m1/video-keyframe-flag.md b/quest/m1/video-keyframe-flag.md new file mode 100644 index 0000000000..7c97c29d20 --- /dev/null +++ b/quest/m1/video-keyframe-flag.md @@ -0,0 +1,24 @@ +# [S] Encoded video knows its keyframes + +## Goal + +`moq_video::encode::Encoded` says whether an access unit is a keyframe, so the +capture `Control::cut()` throttle counts every keyframe, including the +encoder's own GOP cadence. Today it sees only forced and opening keyframes, so +a cut requested just after a cadence keyframe still forces another one. + +## Plan + +- Every backend already knows whether it produced a keyframe; carry it on + `Encoded`. Whether that is additive depends on whether `Encoded` is + `#[non_exhaustive]`; if it is not, this goes to `dev`. +- The throttle in the capture driver treats any keyframe as satisfying a + pending cut and restarting the spacing window, matching what JS already does. +- Test with a backend whose GOP produces a keyframe right before a requested + cut, asserting no extra keyframe. + +Public API: one field or accessor on `Encoded`. Wire: none. + +## Related + +- [#4184](https://github.com/moq-dev/moq/pull/4184) - the `Control::cut()` this completes