Skip to content

fix(net): mock resets carry only codes; ietf publisher cancels with CANCELLED - #7099

Merged
kixelated merged 4 commits into
mainfrom
quest/m1/mock-reset-codes
Oct 28, 2026
Merged

kixelated merged 4 commits into
mainfrom
quest/m1/mock-reset-codes

Conversation

@kixelated

@kixelated kixelated commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Finishes quest/m1/mock-reset-codes.md.

Problem

js/net's mock transport built each stream direction from a TransformStream. A reset (writable.abort(reason)) or STOP_SENDING (readable.cancel(reason)) passed the local reason object straight to the peer. Real WebTransport carries only a code: a WebTransportError's streamErrorCode, or 0 for anything else. Tests could therefore assert on messages that never cross a real wire. One such case hid a wrong code on the wire.

Approach

  • Mock: each direction is now a hand-built WritableStream/ReadableStream pair. The sink's abort and the source's cancel error the other end with { source: "stream", streamErrorCode }, built from the reason's code (0 for a plain Error). Unlike a transformer cancel hook, this doesn't make abort()/cancel() reject. Backpressure, the per-chunk copy, and a session close failing every open stream all behave as before.
  • ietf publisher (wire fix): a group stream that ends because the subscriber left or a REQUEST_UPDATE excluded the group, and a fill cancelled by the subscriber leaving, were reset with plain Errors. On a real wire that sends INTERNAL_ERROR (0). They now reset with CANCELLED (1), which is what the draft asks for and what the Rust publisher sends (Error::Cancel).
  • Tests: the 4 draft-22 publisher tests now assert code: StreamCode.Cancel where they used to check reason text. The new mock.test.ts pins the mock's behavior: a reset or stop reaches the peer as a code with no local message; a coded reason keeps its code; a write parked on a full peer gives up when the peer stops.

Verified: the new mock tests fail on the old mock (2 of 4), and the parked-write test hangs when the wake on stop is removed. With the new mock, the 4 publisher tests got remote error: 0 until the publisher fix.

Impact

  • Public API: none.
  • Wire (moq-transport): the publisher's group and fill streams, when the subscriber leaves or a range update excludes the group, are now reset as CANCELLED instead of INTERNAL_ERROR.

Choices made without asking

  • Reproduce against a real peer: the quest asked for this, but I relied on the code path instead. Writer.reset(plain Error) calls withCode, which hands the transport the raw Error, and both the WebTransport spec and the qmux fallback send 0 for that (see the toTransport doc in js/net/src/error.ts). The same reasoning covers the WebSocket path. I did not run a separate interop run.
  • The other 5 tests named in the quest (2 lite publisher, 3 reload/connect setup) pass unchanged under the faithful mock. That holds on main and on moq-dev/moq#6988's branch with this change applied: all 2508 tests pass there. Their failures in fix(js): yield host tasks through the injected clock #6988's prototype most likely came from the transformer cancel hook making abort() reject. For example, reload.test.ts awaits writable.abort(toTransport(...)). None of them asserts a reset reason that the peer couldn't observe, so I left them alone.

Checks

  • just js check-changed (biome, tsc, builds of net and its dependents): pass
  • just js test-changed (net and every dependent package): pass, 0 failures
  • quest check --base origin/main: pass

Follow-ups

  • None from this change.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 3 commits October 28, 2026 06:16
…ANCELLED

The mock transport handed the peer the local reset/stop reason object,
which real WebTransport cannot carry. Build each stream direction from a
WritableStream/ReadableStream pair whose abort and cancel hooks deliver
only the stream error code (0 for a plain Error).

That exposed the ietf publisher resetting group and fill streams with
plain Errors (INTERNAL_ERROR on the wire) when the subscriber left or a
REQUEST_UPDATE excluded the group. Reset those as CANCELLED, as the draft
and the Rust publisher do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title The JS mock transport carries only reset codes fix(net): mock resets carry only codes; ietf publisher cancels with CANCELLED Oct 28, 2026
@kixelated
kixelated marked this pull request as ready for review October 28, 2026 13:26
@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-28T13:28:08.968853Z 6975a78 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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6975a78c19

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread js/net/src/mock.test.ts Resolved

@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: 6975a78c198a6a790b912f7c3fc65a30ac0c400b

No additional actionable correctness bugs found. The direction is sound: the mock no longer leaks local error messages to its peer, and subscriber-driven group/fill cancellations now pass through the existing stream-code mapping as CANCELLED rather than INTERNAL_ERROR. The explicit stream pair is justified by the need to translate abort/cancel reasons while waking backpressured writes; no public API change is needed.

The test synchronization concern at js/net/src/mock.test.ts:50 is already covered by the independent finding; no duplicate inline comment added.

Verification: static inspection of the diff, mock lifecycle/backpressure paths, publisher cancellation paths, and transport error mapping. I did not run tests or real-peer interop.

(Written by OpenAI)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@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: 47b84bcc-b4cc-4470-a6e9-e33596bb96f9
Commits

Reviewing files that changed from the base of the PR and between 6975a78 and e39f2a5.

Files selected for processing: 1
  • js/net/src/mock.test.ts

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

Walkthrough

Publisher cancellation paths now use StreamError with StreamCode.Cancel. MockTransport now uses paired in-memory streams, propagates stream error codes, and applies backpressure to writes. New tests cover error propagation and cancellation during backpressure. The related quest entry and document were removed.

Priority: Normal

Merge Risk: Minimal · up to e39f2

No actionable merge-blocking defect was established in the reviewed changes.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description check Passed The description clearly explains the mock reset-code changes, IETF publisher cancellation changes, tests, impact, and verification results.
Title check Passed The title concisely identifies both main changes: mock resets carrying only codes and IETF publisher cancellation using CANCELLED.
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: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. 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 2 functions across 4 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

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

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 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: e39f2a5b3d203b8b28753a92deb507f171ae4231

Compared with my previous review of 6975a78c198a6a790b912f7c3fc65a30ac0c400b: only the backpressure test changed. The previously referenced synchronization finding is fixed: js/net/src/mock.test.ts:49-51 now waits for write progress instead of a real timer. With the current 256-chunk queue and sequential sink writes, the next write has entered backpressure before cancellation runs. This is a focused, simpler fix; no new actionable bugs found. Production API/wire behavior is unchanged from the prior review.

Verification: static comparison and inspection of the test and mock write/wakeup paths; tests were not run.

(Written by OpenAI)

@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary for head e39f2a5b3d203b8b28753a92deb507f171ae4231:

  • Codex's one finding on 6975a78c19 (the backpressure test waited on a real timer) is fixed in this head, and its thread is resolved.
  • On this head, the automated review found nothing new to act on, and neither did CodeRabbit. CodeRabbit's docstring-coverage warning doesn't block the merge.
  • All 10 checks pass, and quest check --base origin/main passes.
  • No decisions are open and no follow-ups are needed.

Landing through the merge queue.

(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 b8a8b4e Oct 28, 2026
10 checks passed
@kixelated
kixelated deleted the quest/m1/mock-reset-codes branch October 28, 2026 16:21
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