Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ were done or not worth their cost.
- [Dogfood hosted worklets](/quest/m1/dogfood-assets.md) - moq.dev and the moq.pro dashboard host the worklets and call `assets()` after the release
- [Media audio-tone check](/quest/m1/media-audio-tone.md) - the media lane's audio-tone check passes under load, fixed at its cause
- [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
- [IETF request headers](/quest/m1/ietf-dispatch-headers.md) - each bidi request reads its header in its own task, so a slow one never blocks the next
- [END_OF_TRACK placement](/quest/m1/ietf-end-of-track-placement.md) - END_OF_TRACK rides the upstream's Location, and Rust's header stops claiming END_OF_GROUP
- [moq-uring tests under load](/quest/m1/uring-tests-under-load.md) - uring tests pass while parallel checks share locked memory
- [FFI runtime](/quest/m1/ffi-runtime.md) - moq-ffi drives moq on a multi-thread runtime instead of one thread
- [Audio group duration](/quest/m1/audio-group-duration.md) - audio groups span at least 20 ms by default, so small frames don't mint a group each
Expand Down Expand Up @@ -115,6 +117,7 @@ were done or not worth their cost.
- [Benchmark regressions in CI](/quest/m1/bench-ci.md) - PRs get a non-blocking comparison of the Criterion benches they affect, and a nightly trend on main alerts on regressions
- [Mergeable bench buckets](/quest/m1/bench-buckets.md) - moq-bench emits per-interval latency buckets that sum across processes and hosts
- [Relay session bench](/quest/m1/bench-relay.md) - the same scenario through moq-relay's own connection handling
- [Session burst hang](/quest/m1/session-burst-hang.md) - the burst sweep completes at 16 subscriptions and 16+ groups per round
- [Read-only lookup](/quest/m1/read-only-lookup.md) - a live track lookup stops waking the front and every demand watcher
- [Browser benchmarks](/quest/m1/browser-benchmarks.md) - measure JS transport, container, decode, and render costs in an identified browser
- [Generated @moq/net](/quest/m1/rs2ts/README.md) - the browser runs moq-net as TypeScript generated from the Rust source, retiring js/net's hand-written protocol and model code
Expand All @@ -131,6 +134,7 @@ were done or not worth their cost.
- [Rust papercuts](/quest/m1/papercuts-rs.md) - HTTP refusals are counted, and a `u64::MAX` resume is unbounded
- [JS papercuts](/quest/m1/papercuts-js.md) - IETF status 0 keeps the subgroup open, a muted rendition change settles, and bad element attributes warn
- [Drop insertTrack](/quest/m1/js-insert-track.md) - `createTrack` is `@moq/net`'s only way to add a track by hand, as in Rust
- [JS subgroup heads race close](/quest/m1/js-head-race.md) - a stalled publisher no longer pins a subgroup reader past unsubscribe
- [Front parking](/quest/m1/origin-front-parks.md) - an unroutable request waits on a front instead of re-asking on every route-table move
- [Route wakes](/quest/m1/route-wakes.md) - a route change wakes only the fronts it can move, so pool churn stops scaling with served paths
- [Publish channel count](/quest/m1/publish-audio-channel-count.md) - forcing a channel count on an Audio.Capture stops costing the subscriber gaps of silence
Expand Down
24 changes: 24 additions & 0 deletions quest/m1/ietf-dispatch-headers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# [S] A slow IETF request header never blocks the next request

## Goal

`rs/moq-net`'s moq-transport session reads each incoming bidi request
stream's header in its own task, so a request stream whose header stalls
behind flow control never holds up accepting the next one.

## Plan

[#5086](https://github.com/moq-dev/moq/pull/5086) fixed the same pattern for
uni streams: `run_unis` waited for each stream's type before accepting the
next, and stalled under connection flow control. `run_dispatch`
(`rs/moq-net/src/ietf/session.rs`) still reads `id` and `ietf::Body` inside
the accept loop. Move the header read into the per-stream task, keeping the
current error handling: a stream that dies before its header is dropped, and
any other header error still fails the session. JS already handles each bidi
stream in its own task (`#runBidis` in `js/net/src/ietf/connection.ts`), so
this is Rust only (decided 2026-10-08).

Test, beside #5086's `a_silent_stream_does_not_hold_up_the_next`: a silent
bidi request stream does not block a SUBSCRIBE on the next one.

Public API: none. Wire: none.
29 changes: 29 additions & 0 deletions quest/m1/ietf-end-of-track-placement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# [S] END_OF_TRACK rides the upstream's Location

## Goal

When a moq-transport publisher ends a track, `rs/moq-net` and `js/net` send
END_OF_TRACK at the upstream's final Location (5/5 on group 5's stream),
rather than as 6/0 on a new stream. Rust's END_OF_TRACK stream header clears
END_OF_GROUP, as JS's already does.

## Plan

Deferred from [#5077](https://github.com/moq-dev/moq/pull/5077) (decided
2026-10-08 there as conformance polish with no lost data), from Fastly's
follow-up on #5020 (cells `status-end-of-track` and `publish-done`).
Decided 2026-10-08: both in one quest.

- Rust's `write_end_of_track` (`rs/moq-net/src/ietf/publisher.rs`) builds its
header from `GroupFlags::default()`, which sets END_OF_GROUP; JS clears it.
- Moving onto the upstream's Location means writing the status on the last
group's own stream when it is still open; settle what happens when that
stream has already finished.

Test in both languages: a track ending after group 5 object 5 delivers
END_OF_TRACK at 5/5, and an END_OF_TRACK on its own stream does not claim
END_OF_GROUP. Fastly's moq-relay-interop harness is external, so the PR
notes the change for their next rerun of those two cells.

Public API: none. Wire: no format change, but a peer sees END_OF_TRACK at a
different Location.
24 changes: 24 additions & 0 deletions quest/m1/js-head-race.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# [S] JS subgroup heads race the subscription closing

## Goal

In `@moq/net`'s IETF subscriber, every await on a subgroup stream before its
group producer exists (the FIRST_OBJECT `peekU62()` and the first
`decodeMaybe`) ends as soon as the subscription closes. A stalled publisher no
longer keeps the Reader, its handler, and the Tail entry alive until the
stream moves or the session closes.

## Plan

Found by the review of [#5069](https://github.com/moq-dev/moq/pull/5069)
(the FIRST_OBJECT backport). Rust's `recv_group` already races these reads
against the subscription; mirror it in `js/net/src/ietf/subscriber.ts`.

Decided 2026-10-08: `main` only, no `release` backport. Only a stalled
publisher is affected, and closing the session clears it.

Test: a publisher opens a subgroup stream and stalls before its first object;
unsubscribing releases the reader and its tail entry without waiting on the
stream.

Public API: none. Wire: none.
21 changes: 21 additions & 0 deletions quest/m1/session-burst-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# [S] The session burst bench completes at every shape

## Goal

`rs/moq-net/benches/session.rs`'s `burst` sweep runs to completion at 16
subscriptions and 16 or more groups per round, with or without the kio
budget, and the sweep covers those shapes again.

## Plan

Found while landing serve-budget
([#5088](https://github.com/moq-dev/moq/pull/5088)), which adds the `burst`
axis: with that axis applied, the bench hangs at those shapes without the
budget too, so the sweep was limited to shapes that complete. Decided 2026-10-08:
treat it as a possible session stall, not a bench setup limit. Find whether
it is cache size, stream credit, or a real stall, fix it at the cause, and
add a regression test if the cause is in the session rather than the bench.

## Required

- [A busy task yields within a budget](/quest/m0/serve-budget.md) - adds the `burst` axis
Loading