Repository navigation
fix: intermittent first-request stall on Bun serve under CPU load - #46436
aman-kumar-gw wants to merge 1 commit into
Conversation
…heduler flush) Under CPU load, `opencode serve` on Bun intermittently hangs the first request for tens of seconds. The root cause is a Bun node:http dispatch starvation: the connection is accepted and read natively but the JS `request` event is never emitted while `setImmediate`-style work is starved in the event loop. Effect's default scheduler flushes fiber dispatch through `globalThis.setImmediate`, which hits the same starvation. Route the flush through a MessageChannel macrotask (with a setImmediate/setTimeout fallback) via the existing effect patch. Ports are unref'd so short-lived CLI processes still exit. Cuts the stall rate ~100% -> ~0.3% under heavy contention.
|
Hey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
|
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
Issue for this PR
Closes #46437
Type of change
What does this PR do?
On Bun,
opencode serveintermittently hangs its first request for tens of seconds under CPU load, then recovers (startup-only). I traced it end to end: the request-handler fiber is never forked — the TCP connection is accepted and the request bytes are read into userspace (rx_queue=0), but Bun'snode:httpnever emits the JSrequestevent while the loop is parked inepoll_pwait2, so Effect never sees the request. It's a Bun regression: 1.3.11 doesn't stall, 1.3.12/1.3.13/1.3.14 do —setImmediate-style work gets starved under load.Effect's default
MixedSchedulerflushes fiber dispatch throughglobalThis.setImmediate, which hits the same starvation. This routes that flush through aMessageChannelmacrotask instead (with asetImmediate/setTimeoutfallback) — a different event-loop scheduling path than re-enteringsetImmediate, which keeps the loop turning over so Bun's pendingnode:httpdispatch runs. Ports areunref'd so short-lived CLI runs still exit (the default scheduler is process-wide, not justserve). Delivered through the existingpatches/[email protected].How did you verify your code works?
Cold-cycled
opencode serveon a 2-vCPU container under CPU contention and timed the first request (>8scounted as a stall):Screenshots / recordings
N/A (not a UI change).
Checklist