From 31941d8f0be0bba66639561138ac3dfe633ec4f6 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Sat, 10 Oct 2026 06:53:41 -0700 Subject: [PATCH 1/7] quest: plan moqsrc reconnect Co-Authored-By: Claude Opus 5.5 --- quest/m1/README.md | 1 + quest/m1/moqsrc-reconnect.md | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 quest/m1/moqsrc-reconnect.md diff --git a/quest/m1/README.md b/quest/m1/README.md index ef52e591c3..6603157e06 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -198,3 +198,4 @@ ladders. - [JS restart keeps the request](/quest/m1/js-restart-keeps-request.md) - a resolved `@moq/net` request survives a Restart, as in Rust - [WebGPU on Safari](/quest/m1/webgpu-safari.md) - the WebGPU renderer is verified on Safari 26 for macOS and iOS - [A/V sync across a break](/quest/m1/watch-break-av-sync.md) - `@moq/watch` never plays pre-break audio out of sync with pre-break video +- [moqsrc reconnect](/quest/m1/moqsrc-reconnect.md) - `moqsrc` redials after losing its relay and resumes on the same pads diff --git a/quest/m1/moqsrc-reconnect.md b/quest/m1/moqsrc-reconnect.md new file mode 100644 index 0000000000..0f60562173 --- /dev/null +++ b/quest/m1/moqsrc-reconnect.md @@ -0,0 +1,26 @@ +# [S] moqsrc survives losing its relay connection + +## Goal + +`moqsrc` survives losing its relay connection: it redials with moq-tokio's +reconnect loop, keeps its pads, and resumes on the next `Start`, as it +already does for a publisher restart. Only a refusal (`NotFound`, +`Unauthorized`) is fatal. + +## Plan + +Planned 2026-10-10 as a follow-up of #5191, which made `moqsrc` follow its +path's announcements (`origin::Consumer::follow`) and hold its pads from +`End` to `Start`, but kept its one-shot dial: losing the relay connection is +still a session error. + +- Dial through moq-tokio's reconnecting client rather than a single connect, + so a dropped connection redials and announcements resume. While + disconnected, pads are held exactly as after an `End`. +- Refusals stay fatal, as #5191 decided for the catalog: a refused connect or + path errors on the bus instead of redialing forever. +- Test end to end through a loopback relay: kill the relay mid-playback, + restart it, republish, and require frames on the same pad by name with no + bus error. + +Public API: behavior only (no new property). Wire: none. From 86ffbbcb0924c7ea926c8f85176c4f23f838849c Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Sat, 10 Oct 2026 07:05:09 -0700 Subject: [PATCH 2/7] quest: moqsrc reconnect retries without limit Address review: the default 10s backoff would end the loop on a long outage. Also say where each refusal surfaces and which publisher the test uses. Co-Authored-By: Claude Opus 5.5 --- quest/m1/moqsrc-reconnect.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/quest/m1/moqsrc-reconnect.md b/quest/m1/moqsrc-reconnect.md index 0f60562173..665b57aa41 100644 --- a/quest/m1/moqsrc-reconnect.md +++ b/quest/m1/moqsrc-reconnect.md @@ -12,15 +12,21 @@ already does for a publisher restart. Only a refusal (`NotFound`, Planned 2026-10-10 as a follow-up of #5191, which made `moqsrc` follow its path's announcements (`origin::Consumer::follow`) and hold its pads from `End` to `Start`, but kept its one-shot dial: losing the relay connection is -still a session error. +still a session error. Start after #5191 merges. - Dial through moq-tokio's reconnecting client rather than a single connect, so a dropped connection redials and announcements resume. While disconnected, pads are held exactly as after an `End`. -- Refusals stay fatal, as #5191 decided for the catalog: a refused connect or - path errors on the bus instead of redialing forever. -- Test end to end through a loopback relay: kill the relay mid-playback, - restart it, republish, and require frames on the same pad by name with no - bus error. +- Retry without limit (`backoff.timeout = 0`), as `moqsink` does: the default + 10s budget would turn a longer outage into a bus error. +- Refusals stay fatal, as #5191 decided for the catalog. They surface in two + places: an `Unauthorized` dial ends the reconnect loop (`is_auth`), and a + `NotFound` path or catalog arrives on a request after a successful redial. + Both error on the bus instead of redialing forever. +- Test end to end through a loopback relay: kill the relay mid-playback, keep + it down past the default 10s budget, restart it, and require frames on the + same pad by name with no bus error. Publish with `moqsink`, which reconnects + on its own, so the test exercises `moqsrc` resuming rather than a publisher + that never came back. Public API: behavior only (no new property). Wire: none. From 29c8e03f3dca38302f97d99cf69924331fbbdee9 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Sat, 10 Oct 2026 07:15:50 -0700 Subject: [PATCH 3/7] quest: moqsrc reconnect names Forbidden as a refusal Co-Authored-By: Claude Opus 5.5 --- quest/m1/moqsrc-reconnect.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/quest/m1/moqsrc-reconnect.md b/quest/m1/moqsrc-reconnect.md index 665b57aa41..5335542ca8 100644 --- a/quest/m1/moqsrc-reconnect.md +++ b/quest/m1/moqsrc-reconnect.md @@ -20,9 +20,9 @@ still a session error. Start after #5191 merges. - Retry without limit (`backoff.timeout = 0`), as `moqsink` does: the default 10s budget would turn a longer outage into a bus error. - Refusals stay fatal, as #5191 decided for the catalog. They surface in two - places: an `Unauthorized` dial ends the reconnect loop (`is_auth`), and a - `NotFound` path or catalog arrives on a request after a successful redial. - Both error on the bus instead of redialing forever. + places: an `Unauthorized` or `Forbidden` dial ends the reconnect loop + (`is_auth`), and a `NotFound` path or catalog arrives on a request after a + successful redial. Both error on the bus instead of redialing forever. - Test end to end through a loopback relay: kill the relay mid-playback, keep it down past the default 10s budget, restart it, and require frames on the same pad by name with no bus error. Publish with `moqsink`, which reconnects From 421562270be52592a5bd4a1ff96a6cc89eb496c6 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Sat, 10 Oct 2026 07:23:33 -0700 Subject: [PATCH 4/7] quest: moqsrc reconnect goal lists Forbidden Co-Authored-By: Claude Opus 5.5 --- quest/m1/moqsrc-reconnect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quest/m1/moqsrc-reconnect.md b/quest/m1/moqsrc-reconnect.md index 5335542ca8..82b093a833 100644 --- a/quest/m1/moqsrc-reconnect.md +++ b/quest/m1/moqsrc-reconnect.md @@ -5,7 +5,7 @@ `moqsrc` survives losing its relay connection: it redials with moq-tokio's reconnect loop, keeps its pads, and resumes on the next `Start`, as it already does for a publisher restart. Only a refusal (`NotFound`, -`Unauthorized`) is fatal. +`Unauthorized`, `Forbidden`) is fatal. ## Plan From feaca8e56f08b0a2999c4ab1f6f1bd6fe2eba138 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Sat, 10 Oct 2026 07:27:19 -0700 Subject: [PATCH 5/7] quest: moqsrc reconnect keeps settled CONNECT statuses fatal and updates docs Co-Authored-By: Claude Opus 5.5 --- quest/m1/moqsrc-reconnect.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/quest/m1/moqsrc-reconnect.md b/quest/m1/moqsrc-reconnect.md index 82b093a833..83c233b1b5 100644 --- a/quest/m1/moqsrc-reconnect.md +++ b/quest/m1/moqsrc-reconnect.md @@ -4,8 +4,9 @@ `moqsrc` survives losing its relay connection: it redials with moq-tokio's reconnect loop, keeps its pads, and resumes on the next `Start`, as it -already does for a publisher restart. Only a refusal (`NotFound`, -`Unauthorized`, `Forbidden`) is fatal. +already does for a publisher restart. Only a refusal is fatal: a settled +CONNECT status (such as `Unauthorized` or `Forbidden`) or a `NotFound` path +or catalog. ## Plan @@ -20,13 +21,15 @@ still a session error. Start after #5191 merges. - Retry without limit (`backoff.timeout = 0`), as `moqsink` does: the default 10s budget would turn a longer outage into a bus error. - Refusals stay fatal, as #5191 decided for the catalog. They surface in two - places: an `Unauthorized` or `Forbidden` dial ends the reconnect loop - (`is_auth`), and a `NotFound` path or catalog arrives on a request after a - successful redial. Both error on the bus instead of redialing forever. + places: the reconnect loop already ends on an auth failure or any CONNECT + status other than 408/429/502/503/504 (`status_retryable`), and a `NotFound` + path or catalog arrives on a request after a successful redial. Both error + on the bus instead of redialing forever. - Test end to end through a loopback relay: kill the relay mid-playback, keep it down past the default 10s budget, restart it, and require frames on the same pad by name with no bus error. Publish with `moqsink`, which reconnects on its own, so the test exercises `moqsrc` resuming rather than a publisher that never came back. +- Update `doc/bin/gstreamer.md` so the `moqsrc` lifecycle covers relay loss. Public API: behavior only (no new property). Wire: none. From 465a7de8e354737d132577d1f44f1b00ccccc790 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Sat, 10 Oct 2026 07:31:16 -0700 Subject: [PATCH 6/7] quest: moqsrc reconnect keeps malformed input fatal and tests a refused redial Co-Authored-By: Claude Opus 5.5 --- quest/m1/moqsrc-reconnect.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/quest/m1/moqsrc-reconnect.md b/quest/m1/moqsrc-reconnect.md index 83c233b1b5..b490c71f77 100644 --- a/quest/m1/moqsrc-reconnect.md +++ b/quest/m1/moqsrc-reconnect.md @@ -25,11 +25,15 @@ still a session error. Start after #5191 merges. status other than 408/429/502/503/504 (`status_retryable`), and a `NotFound` path or catalog arrives on a request after a successful redial. Both error on the bus instead of redialing forever. +- Malformed input (a protocol violation or bad catalog) stays fatal too. The + reconnect loop retries every established-session error except auth, so the + implementation must tell a protocol violation from a dropped connection. - Test end to end through a loopback relay: kill the relay mid-playback, keep it down past the default 10s budget, restart it, and require frames on the same pad by name with no bus error. Publish with `moqsink`, which reconnects on its own, so the test exercises `moqsrc` resuming rather than a publisher - that never came back. + that never came back. A second case refuses the redial (for example a 403) + after playback began and requires the terminal bus error. - Update `doc/bin/gstreamer.md` so the `moqsrc` lifecycle covers relay loss. Public API: behavior only (no new property). Wire: none. From d49135d652ce25ed96969c7a633d4dd856aea89e Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Sat, 10 Oct 2026 07:42:05 -0700 Subject: [PATCH 7/7] quest: moqsrc reconnect goal lists malformed input as fatal Co-Authored-By: Claude Opus 5.5 --- quest/m1/moqsrc-reconnect.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/quest/m1/moqsrc-reconnect.md b/quest/m1/moqsrc-reconnect.md index b490c71f77..ce48ec7d67 100644 --- a/quest/m1/moqsrc-reconnect.md +++ b/quest/m1/moqsrc-reconnect.md @@ -4,9 +4,9 @@ `moqsrc` survives losing its relay connection: it redials with moq-tokio's reconnect loop, keeps its pads, and resumes on the next `Start`, as it -already does for a publisher restart. Only a refusal is fatal: a settled -CONNECT status (such as `Unauthorized` or `Forbidden`) or a `NotFound` path -or catalog. +already does for a publisher restart. Only a refusal or malformed input is +fatal: a settled CONNECT status (such as `Unauthorized` or `Forbidden`), a +`NotFound` path or catalog, a protocol violation, or a bad catalog. ## Plan @@ -32,8 +32,9 @@ still a session error. Start after #5191 merges. it down past the default 10s budget, restart it, and require frames on the same pad by name with no bus error. Publish with `moqsink`, which reconnects on its own, so the test exercises `moqsrc` resuming rather than a publisher - that never came back. A second case refuses the redial (for example a 403) - after playback began and requires the terminal bus error. + that never came back. Two more cases require a terminal bus error after + playback began: a refused redial (for example a 403), and a session that + ends in a protocol violation. - Update `doc/bin/gstreamer.md` so the `moqsrc` lifecycle covers relay loss. Public API: behavior only (no new property). Wire: none.