Repository navigation
Conversation
Co-Authored-By: Claude Opus 5.5 <[email protected]>
<moq-publish> never closes its connection on unmount: it releases a pooled handle, and the shared session keeps sending the cleanly finished transcript track until the pool's 2 s linger expires. The page's 250 ms GOODBYE_MS was redundant. Keep the quest open for the upstream drain on linger expiry and a real-call check. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
Outcome: the page now unmounts (Written by Claude Opus 5.5) |
|
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 44 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. Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Drops the voice page's 250 ms
GOODBYE_MSwait before unmounting<moq-publish>on hang-up. Quest:quest/m1/voice-goodbye-drain.md. The quest stays open: the drain itself is an upstream change, and the real-call check needs a maintainer.Root cause
The wait assumed that unmounting closes the connection and drops anything not yet sent.
<moq-publish>doesn't do that:disconnectedCallbackonly clears#enabled(moq/js/publish/src/element.ts). The broadcast's tracks close cleanly, and the page'sbindPublishcleanup callsproducer.finish(). The lite publisher keeps writing group streams that are already open after a clean track close.Moq.Connectionhandle releases its pool lease. The shared session lingers forLINGER_MS(2 s,moq/js/net/src/connection/pool.ts) and keeps delivering during that time.Reload's run cleanup callsEstablished.abort(), not the drainingclose()(moq/js/net/src/connection/reload.ts). So the drainingclose()from moq main never runs on this path. The page has noEstablishedto call it on, and the element has no API for it.Unmounting right away is safe today because of the 2 s linger, which outlasts the old 250 ms wait. The linger is still a fixed wait, though, just upstream. To make the goodbye actually drain, the fix belongs in moq-dev/moq (see the recommendation below).
Proof
Run against a local
moq-relaybuilt from the submodule. Each run creates a separate subscriber session that readstranscript.json.zthrough the relay, the way the agent does. The publisher writesclient-ready, waits until the subscriber has it, writessession-ending, and then unmounts right away.<moq-publish>in the browser (el.remove())<moq-publish>in the browserresetShared())remote error: 54Reloadpatched tovoid current.close()Connectionplus@moq/publishBroadcastReloadpatchedThe
Reloadpatch was local only and is not part of this PR.Bun proof script
Run it with
RELAY=http://localhost:4493/ bun goodbye.ts 2000(or0for no linger), againstmoq/demo/relay/localhost.tomlwith the port changed and[stats]removed.Recommendation (upstream, moq-dev/moq)
In
Reload, close with the drainingEstablished.close()instead ofabort()when the loop shuts down, so that the pool's linger expiry andConnection.close()on a private loop both drain.close()is already bounded to about 1 s. The one-line swap fixed every failing case above. Keepabort()for auth rejections and for redirects that are refused. Once that lands and the submodule is bumped, the comment infinish()should say the connection drains instead of mentioning the linger, and the quest can close after a real call.Remaining proof
A real call on new.moq.dev/voice needs a maintainer, because it requires Turnstile and a mic, and the preview browser blocks mic access. Hang up and check that the agent logs the
session-endingrecord (pipecat's_peer_goodbyepath) instead of waiting outconnection_timeout.Checks
quest check,just fix,just check: pass/voicein the dev server renders and returns to idle (the mic is blocked in the preview)Follow-ups
Reloadon close (above).moqsubmodule once it lands, then reword thefinish()comment.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code