mirror of
https://github.com/coder/coder.git
synced 2026-06-03 04:58:23 +00:00
be99b3cb74
## Problem
Commit 386b449 (PR #23745) changed the `OneWayWebSocketEventSender`
event channel from unbuffered to buffered(64) to reduce chat streaming
latency. This introduced a nondeterministic race in `sendEvent`:
```go
sendEvent := func(event codersdk.ServerSentEvent) error {
select {
case eventC <- event: // buffered channel — almost always ready
case <-ctx.Done(): // also ready after cancellation
}
return nil
}
```
After context cancellation, Go's `select` randomly picks between two
ready cases, so `send()` sometimes returns `nil` instead of `ctx.Err()`.
With the old unbuffered channel the send case was rarely ready (no
reader), masking the bug.
## Fix
Add a priority `select` that checks `ctx.Done()` before attempting the
channel send:
```go
select {
case <-ctx.Done():
return ctx.Err()
default:
}
select {
case eventC <- event:
case <-ctx.Done():
return ctx.Err()
}
```
This is the standard Go pattern for prioritizing one channel over
another. When the context is already cancelled, the first select returns
immediately. The second select still handles the case where cancellation
happens concurrently with the send.
## Verification
- Ran the flaky test 20× in a loop (`-count=20`): all passed
- Ran the full `TestOneWayWebSocketEventSender` suite 5× (`-count=5`):
all passed
- Ran the complete `coderd/httpapi` test package: all passed
Fixes coder/internal#1429