diff --git a/quest/m1/README.md b/quest/m1/README.md index fb2da76e2c..e49a32b3ab 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -76,6 +76,7 @@ above them, since the epoch anchor requires it. - [Live largest location](/quest/m1/largest.md) - `largest()` replaces `latest()` in Rust and JS as a live stream of the track's largest location, known before the first group from the publisher's report - [Untimed lite-07](/quest/m1/lite-untimed.md) - lite-07 carries an untimed track in both languages; lite-05/06 write send time - [Live TS clock validation](/quest/m1/ts-live-clock.md) - resolve the local PCR-rate failure with reproducible timing evidence and CI controls +- [Slow source fails](/quest/m1/slow-source.md) - an export whose source runs further off real time than the output may follow fails promptly naming the rate, instead of dropping frames for hours - [Same-instance TS resume](/quest/m1/ts-same-instance-resume.md) - prove valid continuation and fix the unexpected final exporter failure without weakening identity - [More tests under load](/quest/m1/test-flakes-2/README.md) - the second round of load-only failures, one quest per flake, fixed at the cause - [Plan: a public model](/quest/m1/model-public-surface.md) - every crate-private model item is made public or unnecessary, so a custom publisher or subscriber builds from the public model alone diff --git a/quest/m1/slow-source.md b/quest/m1/slow-source.md new file mode 100644 index 0000000000..46c8ff1f70 --- /dev/null +++ b/quest/m1/slow-source.md @@ -0,0 +1,48 @@ +# [S] A source the output cannot follow fails the export promptly + +## Goal + +An export whose source arrives further off real time than the output's +clock may follow ends with an error naming the measured rate, once it has +used half its delay. It no longer drops nearly every frame for hours with +only per-frame "missed its deadline" warnings. A short stall, such as a +WebSocket-to-QUIC upgrade, still drops late frames and recovers. + +## Plan + +Found on #5435: before #5292, `moq import` fed a 20 s TS clip about 22% +slow on CI's debug build. The TS export measured -222,000 ppm, dropped +1,273 frames as late, and exited clean with 3.2 s captured. + +`jitter::Buffer` (`rs/moq-mux/src/jitter.rs`) already bails when the source +is out of tolerance, but only once the steered drift sits at `MAX_DRIFT`. +At `MAX_SLEW` (0.075 Hz/s of 27 MHz) the steered clock needs about 3 hours to +reach 30 ppm, so a grossly slow source never trips it. The rate itself is +known within a few `STEER` steps. + +Decided with the maintainer on 2026-10-13: + +- Fail loud, not just warn: a source the output can never follow is refused. +- The check lives in the shared jitter buffer, so TS, FLV, and MKV export + fail the same way. Audio decode is out of scope: `moq-audio` sizes its + delay with its own estimator and doesn't steer a clock. +- The rule is the existing one minus "the steered clock is at its limit": + the measured rate is past `MAX_DRIFT` and half the delay is gone. No new + constant. Rejected: a run of a delay's worth of consecutive drops, a new + heuristic beside the rate the buffer already measures. +- Prove with mocked time that a stall shorter than half `RATE_WINDOW` (the + envelope's own bound) doesn't trip it, including an early stall when only + a few floors exist. If the envelope can't tell the two apart that early, + fix the measurement rather than adding a minimum span. +- Regressions: a source 22% slow fails within a few seconds of decode time + with the rate in the error; one 400 ppm off (the existing counted case) + fails once half the delay is gone; sources within 30 ppm never fail. +- Update any doc or comment that says late frames only drop, inline. + +Public API: none; an export that silently degraded now returns an error. +Wire: none. + +## Related + +- [Live TS clock validation](/quest/m1/ts-live-clock.md) - a local run measured -1382 ppm and exited clean; with this rule it fails loudly, which is evidence for that quest, not a blocker +- [#5435](https://github.com/moq-dev/moq/pull/5435) - the duration-fidelity investigation that found this