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/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ transport, benchmark tooling); worktrees isolate commits, not semantics.

- [Play harness](/quest/m1/play-harness.md) - moq play's tune-in, rendition-switch, and drain logic runs in per-PR CI without a device
- [Missing fetch group](/quest/m1/fetch-missing-group.md) - HTTP /fetch answers 404 and `moq fetch` fails cleanly for a group the track lacks
- [JS fetch answer](/quest/m1/js-fetch-answer.md) - js/net's lite fetch settles on the publisher's answer, and a JS publisher's miss resets with NotFound
- [libmoq hidden opt-in](/quest/m1/libmoq-hidden.md) - `moq_origin_announced` takes a `hidden` flag so C callers can list `.`-named broadcasts
- [lite-07 stream count](/quest/m1/lite-stream-count.md) - moq-lite-07 replaces SUBSCRIBE_DROP with a group-stream count in SUBSCRIBE_END, like moq-transport
- [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
Expand Down
32 changes: 32 additions & 0 deletions quest/m1/js-fetch-answer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# [S] JS lite fetch waits for the publisher's answer

## Goal

`js/net`'s lite `fetchGroup` resolves only once the publisher has answered:
the first response byte, or a FIN for an empty group. A missing group rejects
the fetch itself, and every coalesced caller sees the same rejection, instead
of receiving a group whose first `readFrame()` fails. A JS publisher that
cannot serve a group resets the stream with `NotFound`, not a generic error,
so a Rust or JS subscriber can tell a miss from a failure.

## Plan

- Rust already behaves this way since #4164, which waits in the lite
subscriber before accepting and rejects on reset. Mirror it: resolve after
the first response byte or an empty-group FIN, and reject on reset. Today
the fetch path returns its mirror before the response arrives; the stream
reader can already block until data or FIN and throw on reset.
- The publisher side throws a plain error for a local miss, which reaches the
wire as a generic reset code. Give it the `NotFound` code the Rust side uses.
- The IETF JS path refuses `fetchGroup` outright and is out of scope.
- Tests in the lite integration suite: a missing group rejects the fetch, a
coalesced second caller rejects too, an existing group is unchanged, and a
JS publisher's miss reaches a subscriber as `NotFound`.

Public API: none; a behavior change in when `fetchGroup` settles. Wire: no

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Report the fetchGroup behavior as public API impact

Consumer.fetchGroup() is exported in js/net/src/track.ts, and changing when its promise settles and where a missing-group error surfaces changes its observable contract. Labeling the public API impact as none can cause the implementation to skip the required API-impact assessment; describe this as a behavioral public API change instead. (Written by GPT-5.6 Sol)

AGENTS.md reference: AGENTS.md:L53-L58

Useful? React with 👍 / 👎.

format change; a miss resets with the existing `NotFound` code instead of a
generic one.

## Related

- [#4164](https://github.com/moq-dev/moq/pull/4164) - the same fix in Rust
Loading