Skip to content

test(interop): cover late join and FETCH of a past group - #7015

Merged
kixelated merged 5 commits into
mainfrom
quest/m1/interop-coverage/late-join
Oct 28, 2026
Merged

kixelated merged 5 commits into
mainfrom
quest/m1/interop-coverage/late-join

Conversation

@kixelated

@kixelated kixelated commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds the late-join and FETCH interop coverage from quest/m1/interop-coverage/late-join.md to the in-tree tail suite (just test interop --tail, which runs in every --versions pass, including the nightly --versions ietf), and finishes that quest:

  • Late join (run_late_pair, new late mode in both raw tail clients): Rust to Rust and Rust/Node/Bun in both directions, through the relay. The publisher writes group 0's first two objects before any subscriber exists and leaves the group open. The subscriber joins at the latest group (no range, as a player does) and reports on stdout once it has read those two objects. Only then does the harness release the rest of group 0 and group 1. A join that skips the head stalls, so the case cannot pass on timing.
  • FETCH of a past group (run_fetch_round <pub>, new cached mode in the JS tail client): the CLI FETCHes group 1 of a finished track from the Rust publisher and from each native JS runtime. Each group holds three objects with distinct bytes, and the check requires exactly those three, in order, with the right group, index, and size. This replaces the old Rust-only FETCH of a one-object group 0.
  • @moq/web-transport 0.1.5 to 0.1.6 in test/interop/clients/js-native and test/receive-credit. 0.1.6 (moq-dev/web-transport#470) reports a peer's RESET_STREAM and STOP_SENDING as a WebTransportError carrying source: "stream" and the code, as browsers do. It also sends the reason's code from abort() / cancel() instead of 0.
  • The finished quest file and its links are deleted.

The four cells this fixes

With 0.1.5, the four late join cells from a native JS publisher to the Rust subscriber (js-native-node and js-native-bun, drafts 18 and 22) failed:

  1. The relay cancels a request it no longer needs by resetting the request stream. Rust's cancel_group_fetch aborts both halves, on every draft.
  2. On Node and Bun, the polyfill rejected the read with a plain Error("RESET_STREAM: 1") that had no source or streamErrorCode.
  3. malformed() in js/net/src/ietf/request_stream.ts relies on source to tell a reset from bad bytes, so it read the cancellation as a malformed request and closed the session with PROTOCOL_VIOLATION.
  4. The relay's group-0 stream from that publisher then failed with the session's code.

Browsers were never affected. With 0.1.6, all four pass, and @moq/net is unchanged.

Results (local, head 92b5fb3)

Pass CLI FETCH (rust, node, bun publishers) late join
moq-lite (auto) pass all 5 pass
moq-transport-18 pass all 5 pass
moq-transport-22 pass all 5 pass

Decisions (made by the maintainer)

  • Where to fix the reset classification: in the polyfill (moq-dev/web-transport), not @moq/net. Released as @moq/web-transport 0.1.6 and bumped here. The temporary local malformed() patch from the investigation was never committed and is not in this PR.
  • JS subscribers and FETCH: Rust-only FETCH coverage is accepted for now. @moq/net's moq-transport subscriber has no FETCH (track.Consumer.fetchGroup() is rejected there), so the FETCH round uses only Rust as the subscriber. JS subscribers are covered by the late-join lane. JS IETF subscriber FETCH is listed under follow-ups.
  • Landing with red cells: moot. The fix shipped, so no cell is skipped.

Choices made without asking

  • Raw tail-track clients with a stdin/stdout handshake, rather than a hang catalog plus a slow GOP in the media matrix. The handshake makes the head-before-subscriber ordering deterministic, which is what the quest's "cannot pass on timing" asks for. The catalog-written-once shape is the same case: a group whose head predates the subscriber and stays open.
  • The late joiner names no range and uses a 5 s max delay, so it joins the latest group as a player does without the budget skipping group 0 when group 1 arrives.
  • Pairs run Rust-to-JS and JS-to-Rust through the relay, as the tail lanes do, and the lanes run in the moq-lite pass too.
  • On moq-transport, JS subscribers request neither a fill nor a joining FETCH. On draft 22 they subscribe from the current group's start; on draft 18 the Rust relay replays the group on the subscription. The README says so.

Impact

Public API: none. Wire: none. Test-harness only: interop-tail and tail.ts gain late (and tail.ts gains cached), plus new late join and per-publisher CLI FETCH cells in the report. Test dependency: @moq/web-transport ^0.1.6.

Checks

  • just test interop --tail --versions auto,moq-transport-18,moq-transport-22: all checks pass on all three versions, including the four cells above.
  • just test interop --all: all checks pass (180 PASS, no FAIL or SKIP).
  • just check: pass. quest check --base origin/main: pass.

Suggested follow-ups

  • JS IETF subscriber FETCH and head recovery. Give @moq/net's moq-transport subscriber fetchGroup, plus a joining FETCH or fill on a mid-group join, then add JS subscribers to the CLI FETCH round. Today a strict third-party relay would cut a JS subscriber's join to the next group boundary (see the comment at js/net/src/ietf/subscriber.ts on the SUBSCRIBE filter).
  • Branch-scoped checks skip the Rust interop clients. When only test/interop/clients/rust/ changes, just fix and just check neither rustfmt nor clippy those moq-cli examples.
  • Draft-18 cancellation spelling. Rust cancels a draft-18 FETCH by resetting its stream, while the JS side treats FIN as the draft-18 cancel. Worth checking against the concurrent moq-transport request-cancellation work.
  • Polyfill leftovers (moq-dev/web-transport, listed in moq-dev/web-transport#470): Server.close() deadlocks while an accept() is pending, Session.closed never rejects on abnormal termination, and a pending read() pins an abandoned reader's native stream.
  • Seen once earlier: the known tail js-native-bun -> rust draft-18 flake that quest/m2/ietf-join-after-finish.md describes.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

kixelated and others added 3 commits October 27, 2026 22:25
… and JS

The tail suite gains a late-join lane, Rust-to-Rust and Rust/Node/Bun in
both directions. The publisher writes group 0's head before any subscriber
exists and releases the rest only after the subscriber reports reading
that head, so only a join from object 0 passes. The CLI FETCH round now
fetches group 1 of a finished track from Rust and each native JS
publisher, requiring its exact three objects.

The native JS publisher's late-join cells fail on drafts 18 and 22: the
Node polyfill reports a peer's RESET_STREAM as a plain error, so js/net
reads the relay's FETCH cancellation as a malformed request and closes the
session. The quest now tracks that remainder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title Interop covers late join and FETCH test(interop): cover late join and FETCH of a past group Oct 28, 2026
…join quest

0.1.6 reports a peer's RESET_STREAM and STOP_SENDING as a WebTransportError
carrying the code, so @moq/net no longer reads the relay's request
cancellation as a malformed message. The four native JS publisher late-join
cells on drafts 18 and 22 now pass, which was the quest's remainder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review October 28, 2026 08:52
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-28T08:53:21.810693Z 92b5fb3 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Automated review by review (OpenAI)

Reviewed commit: 92b5fb3

No actionable bugs found in the changed areas. The direction is sound: publishing the head before discovery and withholding the tail until its explicit acknowledgement makes the late-join check deterministic, while distinct per-object payloads and exact JSON assertions strengthen the past-group FETCH check. Reusing the existing tail clients and bounded harness is simpler than adding a separate media fixture.

Verification: static review of the Rust/JS client changes, harness lifecycle and timeout handling, CLI JSON output, and dependency/lockfile updates; no tests or builds run. The documented JS-subscriber FETCH limitation remains outside this coverage, and the native dependency's implementation was not independently validated.

@coderabbitai

coderabbitai Bot commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cf7fa0ee-e4bb-46bd-b138-30cf8f682e21
Commits

Reviewing files that changed from the base of the PR and between 7c1161e and 92b5fb3.

Files ignored due to path filters: 1
  • bun.lock is excluded by !**/*.lock
Files selected for processing: 11
  • quest/m1/interop-coverage/README.md
  • quest/m1/interop-coverage/late-join.md
  • quest/m1/next-object-cold-copy.md
  • quest/m2/ietf-headless-group.md
  • quest/m2/ietf-join-after-finish.md
  • test/interop/README.md
  • test/interop/clients/js-native/package.json
  • test/interop/clients/js-native/tail.ts
  • test/interop/clients/rust/tail.rs
  • test/interop/interop.sh
  • test/receive-credit/package.json
Files with no reviewable changes: 5
  • quest/m2/ietf-join-after-finish.md
  • quest/m1/interop-coverage/README.md
  • quest/m2/ietf-headless-group.md
  • quest/m1/next-object-cold-copy.md
  • quest/m1/interop-coverage/late-join.md

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 0 remain after this review.

Walkthrough

The interop tests add late-join and CLI FETCH coverage for Rust and selected native JavaScript runtimes. The client tests add late mode and validate group and frame data. The harness plans and runs these cases, and the interop README updates its coverage descriptions and examples. The changes also remove the late-join planning document and its related links.

Priority: Normal

Merge Risk: Minimal · up to 92b5f

No actionable issue was established that would prevent merging after normal checks.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title "test(interop): cover late join and FETCH of a past group" names the two main behaviors the PR adds to the interop tail suite: late-join coverage and FETCH of a past group. The raw summary c…
Description check Passed The description matches the changeset. It explains the late-join harness (run_late_pair, the new late mode in the tail clients), the CLI FETCH change (run_fetch_round, the cached mode in tail.ts), the…
Docstring Coverage Passed Docstring coverage is 90.91% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentati…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "test(interop): cover late join and FETCH of a past group" names the two main behaviors the PR adds to the interop tail suite: late-join coverage and FETCH of a past group. The raw summary confirms both (new late mode in tail clients, run_late_pair, run_fetch_round changes). The title does not mention the @moq/web-transport bump or the quest-file deletion, which are secondary. It is specific and clearly scoped.

Full details: Description check

Explanation

The description matches the changeset. It explains the late-join harness (run_late_pair, the new late mode in the tail clients), the CLI FETCH change (run_fetch_round, the cached mode in tail.ts), the @moq/web-transport 0.1.5 to 0.1.6 bump in the two package.json files, and the deleted quest file and links. It also gives test results and follow-ups, so it is detailed and on-topic.

Full details: Docstring Coverage

Explanation

Docstring coverage is 90.91% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 11 functions across 3 files. (3 skipped: 3 unsupported.)

Finishing Touches
✨ Simplify code
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

Clippy (1.99.0)

Clippy execution timed out

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Landing per the maintainer's merge pick (2026-10-28).

  • Head 92b5fb36362e4246b5675f5578b4448894f7d69d: CI green (12/12), Codex 👍 and CodeRabbit with no findings on this head, quest check --base origin/main passes.
  • just test interop --all on this head merged locally with current main (4fdbad719e, which includes moq-dev/moq#6978 and moq-dev/moq#6976): 180 PASS, no FAIL or SKIP. This includes all three CLI FETCH cells and all five late join cells.
  • The PR body lists the follow-ups for /quest-plan.

(Written by Claude Opus 5.5)

@kixelated
kixelated added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit 596eda5 Oct 28, 2026
12 checks passed
@kixelated
kixelated deleted the quest/m1/interop-coverage/late-join branch October 28, 2026 16:48
kixelated added a commit to michaelstuurman/moq that referenced this pull request Oct 28, 2026
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
kixelated added a commit that referenced this pull request Oct 29, 2026
Resolves conflicts with #6969 (legacy FIN finishes the track, kept alongside
reopening uncovered demand), #7168 (Window::named also waits on a time start;
its JS fills rule joins the quest's remainder), and #7015's late tail mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant