fix(codex): retry capacity failures before stream output - #2
Merged
Conversation
(cherry picked from commit f6a185a559fbb7fdac87d1e0a3fb1644cbdac05e)
(cherry picked from commit 6c6be6445dcae97b4b980de7bf82617d46ab0a16)
There was a problem hiding this comment.
Pull request overview
This PR improves OpenAI Responses (Codex) streaming robustness in the gateway by buffering lifecycle-only SSE events until “stateful” output is produced, and by treating pre-output capacity failures (server_is_overloaded, slow_down) as retryable 503 relay errors. It also prevents transient capacity failures from triggering automatic channel disabling, and adds targeted regression tests for retry/stream behavior and trace “first response” timing resets.
Changes:
- Add overload-code detection helpers and use them to avoid auto-disabling channels on transient capacity failures.
- Buffer Responses SSE “prelude” events and surface pre-output capacity failures as retryable HTTP 503s (without committing downstream output).
- Add helpers + tests to ensure trace first-response state can be reset between retry attempts, and that committed streams can still receive a
response.failedSSE event.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| types/error.go | Adds helpers to detect Codex capacity error codes (server_is_overloaded, slow_down). |
| service/channel.go | Skips auto-disable for overload errors to avoid disabling channels for transient capacity failures. |
| service/channel_first_response_timeout_test.go | Adds regression test ensuring overload errors do not trigger channel disabling. |
| relay/helper/stream_scanner.go | Fixes WaitGroup accounting via defer wg.Done() in stream goroutines. |
| relay/helper/common.go | Adds ResponsesStreamError helper to emit response.failed SSE after downstream stream commit. |
| relay/helper/common_test.go | Tests ResponsesStreamError output and headers when the stream is already committed. |
| relay/common/relay_info.go | Adds ResetFirstResponseTime to allow retries to record a new first-response event. |
| relay/common/relay_info_test.go | Tests ResetFirstResponseTime behavior across attempts. |
| relay/channel/openai/relay_responses.go | Buffers prelude events; converts pre-output overload failures into retryable 503s; resets first-response state before retry. |
| relay/channel/openai/relay_responses_test.go | Adds tests covering buffering, overload retry behavior, and overload-code recognition. |
| dto/openai_response.go | Adds top-level Error field to ResponsesStreamResponse to support error / response.error SSE events. |
| controller/relay.go | Emits response.failed SSE on overload when stream already committed; forces JSON content-type for retryable pre-output overload errors. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
Summary
server_is_overloadedandslow_down) into retryable HTTP 503 relay errorsresponse.failederrors and top-levelerror/response.errorSSE eventsresponse.failedevent when output was already committed or retries are exhaustedThis ports and adapts the original fixes from
f6a185a5and6c6be644onto the current S2 main branch, including its OpenTelemetry relay tracing and stream-scanner changes.Tests
go test ./relay/channel/openai ./relay/common ./relay/helper ./service ./controller ./typesgo test -v ./relay/channel/openai ./relay/common ./relay/helper ./service -run 'ServerOverload|ResponsesStream|ResetFirstResponse'go test ./...ran successfully for all Go subpackages; the root package cannot be set up in this checkout because the generatedweb/classic/dist/index.htmlembed artifact is absentNotes
The race-enabled suite also surfaces pre-existing races around the global logger and existing parallel polling tests; the capacity-specific and ordinary package tests pass.