Repository navigation
test(net): cover stalled PROBE writers and pooled viewer reconnects - #8020
Conversation
Quest-Claim: 2e395b5c78dfcf2b
Finishes quest/m2/probe/viewer-followups.md: a stalled PROBE writer test in Rust and JS, a pooled-reconnect test against a fake Increase peer, and a Bandwidth section in the Python API docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 39 minutes. View limit details
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. |
There was a problem hiding this comment.
ℹ️ Minor suggestions only.
Reviewed changes
Reviewed the whole diff: three new test scenarios, a shared JS harness change, and the docs/quest edits. Ran bun test src/connection/pool.test.ts src/lite/subscriber.test.ts in js/net — 170 pass, 0 fail, including all three touched tests. (The Rust suite was not run here: cargo test -p moq-net blocked on a stale build-directory lock in this environment, so I read the test and the memory-transport buffering semantics by hand instead.)
- Stalled writer, Rust — the new unit test relies on
stream_buffer: 0meaning one queued message (matchingzero_buffer_holds_one_message), stalls the first target behind the stream type, moves the viewer through 2/3/4 Mbps, and asserts three exact chunks with nothing pending afterwards. This does pin the coalescing behaviour rather than just the pending state. - Stalled writer, JS —
stallTargetnow stalls only the first target write and can be released by hand, so the new test covers#sendTarget's single-write guard; the existing reset test still exercises the abort path. - Pooled reconnect, JS —
increasePeerplays a raw lite-06 peer and the test verifies a sharedViewerssum before the drop, the exact target after reconnect, and that closing a viewer follows the live handles. - Docs and quest — Bandwidth autosummary section added after Subscribing; the finished quest file and its epic link are removed with no remaining references.
deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed head dd706f03bdee26f8cdffddf0c1ab17c0152f483c against base 0672ad56ce29ae168c7122fe6ece20de08cdc12a.
One P2 finding in the new JS stalled-writer test: its final FIN assumes that receiving target bytes means the sender has finished its write, but the shared write budget can still be yielding. That valid schedule aborts the harness writable and leaves the final EOF assertion waiting indefinitely. The inline comment traces the schedule and suggests synchronizing completion.
Also checked the Rust memory-transport backpressure and exact-chunk assertions, JS intermediate-update/coalescing coverage, existing failure/reset harness paths, shared pooled Viewers ownership across reconnects, the Python exports/docs, and quest retirement. No additional actionable findings in those changes. I read the existing review and have not repeated its documentation suggestion.
Limits: GitHub-only static review. No local commands, test execution, mutation checks, Sphinx build, or quest tooling were run; the scheduling failure above was derived from the source, not reproduced locally. The PR's reported test results are not independent validation by this review.
…trol Reading a target back only proves its bytes were written: the writer can still be yielding the shared write budget, and a FIN then resets the stream instead of closing it. Drain pending yields with a manual clock before the FIN. List RateControl and RateTarget in the Python Bandwidth reference. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Reviewed the delta since the prior pullfrog review (dd706f0 → 0ef97f9): the test-only FIN settle barrier and the completed Bandwidth docs section. bun test src/lite/subscriber.test.ts (136 pass) and bun test src/connection/pool.test.ts (34 pass) in js/net, including both target tests with the new clock barrier.
- FIN settle barrier — both JS PROBE target tests install a
Manualclock andawait clock.advance(Nano.zero)before the peer FIN. This drains any pending sharedwriteBudgetyield, so#sendTargethas finished its write before the scope cleanup runs; otherwise the cleanup resets the stream andsent.done()never resolves. I traced the mechanism (Budget.poll→yieldNow→Manual.advancedraining until#tasks === 0) and it covers both the yielding and non-yielding schedules. - Bandwidth docs —
RateControlandRateTargetadded to the autosummary and the section intro extended to describe them, completing the prior review's suggestion.RateTarget's FFI re-export is documented as a mock, consistent withGrantand the other re-exported types.
deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Follow-up review of head 0ef97f98f222c32ed51df496d7cd5befa4605b5c against base 344c2be000b2e73bbd693ff243ca1d62fd5ff183, comparing the PR changes with previously reviewed head dd706f03bdee26f8cdffddf0c1ab17c0152f483c and separating the merged main changes.
The previous P2 is fixed. Both target tests now install a manual clock and drain pending work with clock.advance(Nano.zero) before delivering FIN. I traced Writer.write, the shared budget, the manual clock's host-task draining, and #sendTarget cleanup: the barrier settles the final write/yield before FIN can trigger the in-flight-write abort path. The stalled-writer test retains its exact 1 Mbps then 4 Mbps assertions and final EOF check.
Also rechecked the current six-file PR diff, the existing stalled/reset harness paths, pooled reconnect assertions, and the added RateControl/RateTarget documentation. No new actionable findings.
Direction: The barrier fixes the test synchronization without changing production behavior or weakening the coalescing/EOF assertions.
Limits: GitHub-only static review. I did not run Bun/Rust tests, the forced-yield mutation, Sphinx, or quest/gate commands; the author's reported results were not independently reproduced. The exact-head Check workflow was still in progress when inspected. This COMMENT is not merge approval.

Finishes quest/m2/probe/viewer-followups.md, which this PR deletes along with its link in the probe epic.
Problem
moq-dev/moq#7090 shipped viewer PROBE targets but left three gaps:
Reload/poolviewerswiring that carries targets across reconnects had only type checks and the subscriber's wire tests.Approach
a_stalled_probe_writer_sends_only_the_latest_target,rs/moq-net/src/lite/subscriber.rs). Uses the in-memory session withstream_buffer: 0, so the stream holds one unread message, and a peer SETUP advertisingIncrease. The stream type fills the stream and the 1 Mbps target waits in the writer. The test moves the viewer to 2, 3 and 4 Mbps, then the peer reads. It asserts exactly[type, 1 Mbps, 4 Mbps]arrive, as separate writes, and nothing after.a stalled PROBE writer sends only the latest target once it drains,js/net/src/lite/subscriber.test.ts). The existingprobeTargetHarness'sstallTargetwrite can now be released by hand (release()), as well as by the reset the existing test uses. The new test makes the same moves and asserts the peer reads 1 Mbps, then 4 Mbps. Before the FIN it drains pending yields with a manual clock (clock.advance(Nano.zero)): reading a target back only proves its bytes were written, and a writer still yielding the shared write budget would see the FIN reset the stream instead of closing it. The existing target test gets the same barrier.pooled viewers send their summed target to an Increase peer across a reconnect,js/net/src/connection/pool.test.ts).increasePeerplays a raw lite-06 peer on the mock transport: it sends a SETUP advertisingIncreaseand records every PROBE target it reads. No JS session advertisesIncreaseuntil padding, so the test needs a fake peer.[5 Mbps]. Closing one viewer then sends 2 Mbps on the new session, so it follows the live handles rather than a snapshot.py/moq-rs/docs/index.mdgains a Bandwidth section, after Subscribing, listingAllocator,Reservation,RateControl,RateTarget,BandwidthConsumer,ViewersandViewer. Autosummary renders each one's one-line docstring, like the other sections, with a two-line intro like Media's and JSON's.Impact
None. Tests and docs only; no public API or wire change.
Choices made without asking
an_ended_probe_clears_the_estimate. It drivesRecvBandwidthdirectly against the memory transport, the "in-memory session" the quest names. The integration harness (MockSession) can't stall a stream.Increasegate, so the tests use lite-06, the version the existing target tests use.Checks
quest gate nix develop --command just check origin/mainon0ef97f98f2: every selected module passed (py with the Sphinx-Wdocs build, rs with 10,972 tests, js, biome, gh, quest, markdown and the rest).\x05\x80\x0fB@\0\x05\x80\x1e\x84\x80\0...against\x05\x80\x0fB@\0).viewersfrom the reload's second dial fails the post-reconnect assertion.Budget.pollto yield on every write, both target tests time out withoutclock.advance(Nano.zero)before the FIN and pass with it.Follow-ups
None.
Review
Codex, gpt-6.1-sol, medium effort,
quest review --base origin/main, session01a1b1a0-a237-76e0-bc62-ef60528fe1a1:0ef97f98f222c32ed51df496d7cd5befa4605b5c, base43fcb958d5: no findings.Online review threads on
dd706f03bd:🤖 Generated with Claude Code
(Written by Claude Opus 5.5)