Repository navigation
test(executor): fix two websocket test-server races behind CI flakes (MASTRA-771) - #6
Merged
Merged
Conversation
…(MASTRA-771) Root cause 1, keepalive tests (Codex and xAI KeepalivePingDuringUpload WithSession, Sessionless and NonstreamSessionless): the fake upstream wrote response.completed and closed the connection as soon as the pong arrived, before the client's held payload write ran. The client read loop (readUpstreamLoop) then saw the close and invalidated the connection, so the write failed with "use of closed network connection". The server now replies only after it has read the request. In the WithSession variants the same race would send the retry back through the hook and panic on a second close(inWriteHook). Root cause 2, TestWebsocketRetryBindFailureClearsActiveSessionState: the server numbered connections after Upgrade, so a handler descheduled after the handshake could take a later number. The third connection then got number 2, was closed at once, and the second request failed with close 1006. The counter now runs before Upgrade, in dial order. Evidence (GOMAXPROCS=1, stress -p 32, 16 CPU burners): - keepalive Sessionless tests: 153/20000 failures before, all the CI signature; 0/60000 after. - retry bind test: 52/6000 before (1006 or reset on the second request); 0/18000 after. - Deterministic: a 100 ms sleep after the pong wait fails 25/25 runs before and 0/25 after. A 200 ms sleep after the first Upgrade fails 15/15 before and 0/15 after. Production code is unchanged. internal/runtime/executor is identical to upstream v8.0.13. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MASTRA-771 Fix the flaky upstream websocket tests in mobilyze-llc/CLIProxyAPI CI
Context
Failures so far, each passing on rerun:
Facts read from source:
Local isolated runs (50×) and three loaded package runs did not reproduce it. The root cause is not yet established. Scope
Acceptance criteria
Source refs
|
4 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linear: MASTRA-771
Fixes the websocket test flakes that failed about every other
gojob in this repo's CI. Both are races in the test servers, not in production code. The fix is test-only: 3 files, +32/−29.Root causes, each reproduced
1. Keepalive tests (
Test{Codex,XAI}Websockets_KeepalivePingDuringUpload_*, 5 tests)readUpstreamLoop(codex_websockets_session.go:665-688) saw the close and calledinvalidateUpstreamConn(:774), so the released write failed with "use of closed network connection".2. Retry bind test (
TestWebsocketRetryBindFailureClearsActiveSessionState)Upgrade. If connection 1's handler was descheduled after the handshake, the next dial took number 2 and was closed at once.Upgrade. The 101 response is sent only after the count, so numbers follow dial order.Evidence
Reproducer:
GOMAXPROCS=1stress,-p 32, with 16 CPU burners.-raceat GOMAXPROCS=2 found no data race, before or after. So the shared hook variable is not the cause.go test ./...: 100 packages ok.gofmtandgo vetare clean.Upstream
git diff v8.0.13 main -- internal/runtime/executor/is empty, so both races exist unchanged in router-for-me/CLIProxyAPI v8.0.13. This commit applies there as-is. Upstream's CI only runsgo build, so it never sees them.Not changed (observation)
TestXAIWebsocketsExecuteStreamSendsResponseCreateWithPreviousResponseIDleaves a stream goroutine holding a global session lock, so it hangs at-count>=2. CI uses-count=1and is unaffected.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmithwith what you need. Autofix is disabled.