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
1 change: 1 addition & 0 deletions quest/m0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,5 @@ have fixes on `main`: macOS tests (#5335), drill-sensitivity (#5338), loom
- [web-transport releases the qmux fixes](/quest/m0/qmux-credit-upstream.md) - waiting on moq-dev/web-transport#412 and #413 to merge and ship, which qmux credit bumps to
- [qmux credit](/quest/m0/qmux-credit.md) - qmux returns connection credit for dropped and stopped streams and delivers its close frame, on both lines
- [Broadcast epochs](/quest/m0/broadcast-epoch/README.md) - every first-party publisher that can restart mints a fresh route epoch, the newest wins a path, and only routes with the same epoch resume a subscription
- [Keep the winning transport](/quest/m0/drop-ws-upgrade.md) - a connection stays on the transport that won the race; the WebSocket-to-QUIC upgrade and its epochless `Restart` are removed
- [Parked drain](/quest/m0/parked-drain.md) - draining parked groups after a cap rise, as a same-epoch relay handover causes, is near-linear in the backlog, not quadratic
60 changes: 60 additions & 0 deletions quest/m0/drop-ws-upgrade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# [M] A connection keeps the transport that won the race

## Goal

A `moq-tokio` connection whose `https://` race is won by WebSocket stays on
WebSocket for that session's lifetime; nothing migrates it to QUIC. The
pending QUIC dial is cancelled the moment WebSocket wins, as when QUIC wins.
An epochless viewer no longer sees a `Restart` shortly after connecting.

Non-goals: changing the race itself, its head start, or the "WebSocket won"
memo's effect on later connects.

## Plan

Decided with the maintainer on 2026-10-13: remove the WebSocket-to-QUIC
upgrade from #4180. On an epochless route, which is the default for
lite-06, the browser, and the bindings, the upgrade is a `Restart`: players
re-resolve, re-fetch the catalog, and reset decoders right after connecting.
That is a brutal user experience, and nothing shows the upgrade helps outside
CI's debug builds. Rejected: upgrading only when epochs match (keeps the
machinery for a minority of sessions), keeping it as is, and measuring first.

- Delete the upgrade in `rs/moq-tokio` (`connection.rs`'s `upgrade` state and
its handover, `client.rs`'s post-race `Setup` stage) and its tests
(`websocket_upgrades_to_quic`, `a_refused_upgrade_keeps_websocket`).
- Cancel the pending QUIC dial at once when WebSocket wins, deleting #5284's
closed fallback too: a WebSocket session that closes early goes through the
ordinary reconnect, which races again.
- Keep the "WebSocket won" memo (`WEBSOCKET_WON`). Both transports still race
without the head start, so QUIC can still win a later connect. Its only
eviction was a successful upgrade; check what clears it now and document it.
- Remove `moq_net::Session::setup()` unless the GOAWAY drain migration gates
on it; if it does, keep it and say why in its doc. Keep
`Connection::transport()`, which reports the live transport.
- Keep the origin fix from #5443 (`Release` in `model/origin.rs`): GOAWAY
drains and publisher replacement still hand an epochless route over the
same way.
- `js/net` keeps closing the loser as today. This plan's PR deleted the m1
transport-upgrade epic and its JavaScript child, and folded the QUIC-wins
race flake in below.
- Add a regression: when WebSocket wins, the QUIC dial is dropped and no
second session ever starts, with mocked time.
- Absorbs the rest of the QUIC-wins race flake: `quic_winning_opens_one_session`
already holds the fallback handshake, but `fallback.accepted.try_recv()`
only proves the queue is empty at one instant. Observe the loser's
cancellation directly, by a drop or connection-close signal, in both
directions.
- Update docs and comments that describe the upgrade inline, and search the
bindings for the `WebTransport` transport report #4180 added; it stays.

Public API: breaking in moq-net (`Session::setup()` removed, unless kept as
above). Behavior: no QUIC upgrade after a WebSocket win. Wire: none. Report
both in the PR.

## Related

- [#4180](https://github.com/moq-dev/moq/pull/4180) - the upgrade this removes
- [#5284](https://github.com/moq-dev/moq/pull/5284) - the closed fallback this removes
- [#5443](https://github.com/moq-dev/moq/pull/5443) - the origin fix that stays
- [Restart followers](/quest/m1/restart-followers.md) - consumers that follow the `Restart` GOAWAY drains and publisher replacement still send
1 change: 0 additions & 1 deletion quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ above them.
- [Typed refusal reason](/quest/m1/refusal-reason.md) - an auth server's 403 names the reason (including `expired`) and the root and tier, so the relay's session outcomes count and attribute refusals
- [JS track handover](/quest/m1/js-group-handover.md) - a JS track subscription resumes across a route swap from the first frame it lacks, so `test/drain` passes at zero latency budget
- [Drain web connections from accept](/quest/m1/drain-web-accept.md) - a relay drain never exits under an HTTP/1.1 WebSocket client still in TLS or header parsing
- [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 without dropping a group
- [Scope track priority](/quest/m1/track-priority-scope.md) - priority orders one owner's streams, and a shared cluster session is fair across tenants
- [io_uring CI](/quest/m1/uring-ci.md) - PRs touching io_uring code run `just rs uring` on a 6.12+ kernel runner
- [Audio jitter target](/quest/m1/audio-jitter-target/README.md) - the playout target is default in both languages; a manual browser proof and a native trace replay remain
Expand Down
4 changes: 1 addition & 3 deletions quest/m1/js-group-handover.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ Things to settle along the way:
- Resume only between routes with the same epoch. Any other swap is a new
broadcast that announce consumers see as a `Restart`, and players follow
it with a fresh subscription. A route without an epoch never resumes, as
in Rust, so `drain.ts`'s publisher mints an epoch, and the
[transport upgrade](/quest/m1/transport-upgrade/js.md) test publishes
under one too.
in Rust, so `drain.ts`'s publisher mints an epoch.
- `js/watch` and `js/hang` consumers that re-subscribe on `active` changes.
Check whether they still need to.
- Giving up a resumed group no route continues. Mirror Rust's rule from
Expand Down
2 changes: 1 addition & 1 deletion quest/m1/restart-followers.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ Wire: none.

## Related

- [Transport upgrade](/quest/m1/transport-upgrade/README.md) - its "epochless routes signal Restart and need a fresh follower resolution" decision
- [Keep the winning transport](/quest/m0/drop-ws-upgrade.md) - removes the upgrade, so `Restart` no longer follows every WebSocket connect
- [Broadcast epochs](/quest/m0/broadcast-epoch/README.md) - the players that already follow `Restart`
1 change: 0 additions & 1 deletion quest/m1/test-flakes-2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Public API: none. Wire: none.
## Required

- [Interop close code](/quest/m1/test-flakes-2/interop-close-code.md) - the browser close-code test reliably sees `unauthorized` for a refused session
- [QUIC-wins race](/quest/m1/test-flakes-2/quic-winning-race.md) - moq-tokio's QUIC-wins test sets up QUIC's win instead of racing the WebSocket head start
- [Handshake ACK](/quest/m1/test-flakes-2/handshake-ack.md) - the impaired cluster drill's connect survives a lost handshake ACK
- [Auth refresh expiry](/quest/m1/test-flakes-2/auth-refresh-expiry.md) - the auth refresh outage test measures the grant's life on one clock

Expand Down
34 changes: 0 additions & 34 deletions quest/m1/test-flakes-2/quic-winning-race.md

This file was deleted.

85 changes: 0 additions & 85 deletions quest/m1/transport-upgrade/README.md

This file was deleted.

57 changes: 0 additions & 57 deletions quest/m1/transport-upgrade/js.md

This file was deleted.

1 change: 0 additions & 1 deletion quest/m1/ts-live-clock.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,5 @@ public API and wire changes are not expected.
- [Validation PR #5328](https://github.com/moq-dev/moq/pull/5328#issuecomment-6114456593) - retained local failure and process-status evidence
- [Passing full CI](https://github.com/moq-dev/moq/actions/runs/38178905198) - same-head contrast, including real live timing
- [Same-instance resume](/quest/m1/ts-same-instance-resume.md) - independent full-check failure
- [Transport upgrade](/quest/m1/transport-upgrade/README.md) - existing session handover and epoch contract
- [Mux-rate hold #5287](https://github.com/moq-dev/moq/pull/5287) - initial rate publication, and a finished import lingering for its max-age
- [TS AC-3 scheduling](/quest/m1/ts-atsc-ac3.md) - #5306 owns decoder deadlines and unknown-rate startup overflow
3 changes: 0 additions & 3 deletions quest/m3/quic-careful-resume.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ start on the first loss or a mismatched RTT.
`rs/moq-tokio/src/connection.rs`, dialing through the race in
`failover.rs`) seeds a redial from the session it replaces, and
the relay's cluster peers seed from the previous session to the same peer.
The transport-upgrade quest's QUIC dial seeds from nothing, since the
previous session ran over TCP.

Measure time to the encoder's target rate after a reconnect on the impaired
path profile, plus loss and latency during the jump. Ship it on by default
Expand All @@ -42,5 +40,4 @@ only when the jump never makes the first second worse than slow start.

## Related

- [Transport upgrade](/quest/m1/transport-upgrade/README.md) - its first QUIC connection has no seed from TCP; later QUIC reconnects may reuse a remembered estimate
- [noq#815](https://github.com/n0-computer/noq/issues/815) - the careful-resume proposal to n0
9 changes: 5 additions & 4 deletions quest/m3/uring-tcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ Measure before porting, the same way the echo bench
(rs/moq-uring/benches/session_lite.rs) gated the UDP path. The ablation's
number is what justifies the rest of the line.

Decided in the 2026-09-30 audit: moved to m2. The
[transport upgrade](/quest/m1/transport-upgrade/README.md) shrinks the
WebSocket hot path by moving clients to QUIC, and no fleet demand asks for
ring TCP.
Decided in the 2026-09-30 audit: moved to m2, since no fleet demand asks
for ring TCP. (Decided 2026-10-13: the WebSocket-to-QUIC upgrade that would
have shrunk the WebSocket hot path is being removed by
[Keep the winning transport](/quest/m0/drop-ws-upgrade.md), so a WebSocket
session will stay on TCP for its lifetime.)

Decided 2026-10-08: moved to m3. No fleet demand asks for ring TCP; the
ablation stays the gate for the rest of the line.
Expand Down
Loading