Repository navigation
fix(relay): send a failed direct fallback only once - #469
Merged
Merged
Conversation
The relay-fallback quota test counted every non-relay request that reached its fetch mock as a direct send. When the WebSocket relay test before it overran Bun's test and hook timeouts, that test's late teardown deleted OPENCODE_ANTHROPIC_AUTH_DISABLE_PROFILE_HYDRATION during this test, so its plugin also sent GET /api/oauth/profile and the count read 2 (nightly audit run 40076898210). With a longer overrun, the earlier test's own relay and direct requests reached this mock too. Direct sends now count only POSTs to the messages endpoint whose body carries this request's probe text, and relay sends count only payloads with this request's affinity. 'Exactly once' still means once for this request: a relay mutation that calls the direct fallback twice still fails it.
sendRelayHttp calls the direct fallback itself on a relay 5xx and on a relay-only 401. When that direct request failed after it started (for example a connection reset after the body reached Anthropic), its error reached sendViaRelay's outer catch, which, with fallbackToDirect on, called the fallback again: one request, two direct sends, possibly billed twice. The WebSocket -> HTTP relay path ended in the same catch. sendViaRelay now records when its direct fallback has started and rethrows that fallback's own error instead of sending again. A relay that fails before any fallback started still falls back direct once, as before. Red first: the three new 'is not sent again' tests failed with 2 direct sends before this change. Mutation row relay-direct-fallback-sends-once removes the guard and reddens exactly those three.
…anch, so the mutant compiles
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.
While diagnosing last night's mutation-audit baseline failure, a real duplicate-send path turned up in
sendViaRelay. The relay's HTTP 5xx and relay-401 branches (and the WebSocket→HTTP path) call the direct fallback, and if that direct send rejected after it went out (for example a connection reset after Anthropic received it), the outer catch fell back a second time: two physical sends for one request. The fallback now runs at most once per request; a failure after it started is passed to the caller, which retries with its own backoff. A relay failure before any fallback still falls back once. Red-first Core tests and a mutation row.The CI failure itself was test-only: an earlier WebSocket test overran Bun's timeouts and its late reset re-enabled profile fetching, so the relay-fallback test's catch-all mock counted a profile GET as a second direct send. That test now counts only its own sends.