fix(http-bridge): keep idle retirements out of retry circuit - #1677
Open
leventov wants to merge 2 commits into
Open
fix(http-bridge): keep idle retirements out of retry circuit#1677leventov wants to merge 2 commits into
leventov wants to merge 2 commits into
Conversation
Advance a hard-key retry circuit only when bridge retirement owns at least one pending request and that request has emitted no response event. Routine idle socket retirement remains diagnostic but no longer creates phantom failures or premature cooldowns.
Contributor
Author
|
CI follow-up: the first |
This was referenced Aug 10, 2026
Contributor
Author
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
Routine idle HTTP Responses bridge retirement could consume a hard-key retry
circuit strike even when the bridge owned no pending request. One later genuine
pre-response timeout was then misclassified as the second consecutive failure,
opening the cooldown and returning
503 HTTP responses session bridge is cooling downto the client.This PR makes circuit evidence request-owned: retirement records a strike only
when it still owns at least one pending request and that lifecycle has observed
zero response events. Direct retirement derives omitted event evidence from the
same locked ownership snapshot, so an eventful stale-gate request cannot be
misclassified as eventless merely because its caller omitted an optional
handoff. A reader failure hands its explicit pre-drain evidence to the ordinary
retirement path so draining the deque cannot erase genuine failure evidence.
Idle socket churn remains visible in diagnostics but is neutral to the durable
retry circuit.
Type of change
fix:— bug fix (no behavior change beyond the bug)Linked issue: none exists for this incident-derived regression; the exact
idle-retirement-then-timeout sequence is covered at the routed endpoint.
OpenSpec
upstream request and downstream SSE wire formats
Change directory:
openspec/changes/archive/2026-08-10-recover-repeated-clean-close/#1394 originally landed the
recover-repeated-clean-closechange as an activeartifact. This PR adds its missing design record, syncs the already-landed
stable requirements into
openspec/specs/responses-api-compat/, appends thepost-deploy retirement-accounting requirement, verifies it, and archives the
same change. The comparatively large spec diff is lineage closure for #1394;
the new production correction in this PR is the focused retirement guard.
Origin and concurrent work
Landed lineage:
a66f7937) introduced bounded clean-close/silent recovery and thedurable hard-key retry circuit. Its shared retirement boundary treated
response_events_seen == 0as sufficient evidence, which is also true foran idle bridge with an empty pending deque.
3aabe998) added silent-session quarantine through the same bridgelifecycle, and fix(proxy): detect stalled upstream websockets #1579 (
a0a977a6) added upstream WebSocket liveness handlingthrough the same retirement funnel. The new ownership guard keeps those
maintenance/liveness paths neutral when no request is affected.
f2f8f916) recently extended stuck-owner failover on top of fix(http-bridge): stabilize silent and clean-close recovery #1394.This PR does not change its replay eligibility; it only corrects the evidence
used by the shared circuit.
Concurrent work reviewed for overlap:
_retire_stale_pending_http_bridge_sessiontore-sample liveness before closing. It is complementary and shares both the
production hunk and unit-test file; whichever lands second must preserve both
the no-pending ownership guard and the pre-close liveness re-check.
request_submit.pyplus both bridge regression files fordurable operation recovery. It is not a dependency, but is a direct rebase
and lifecycle-regression overlap.
fix(http-bridge): allow long response.create acknowledgements #1620 changes the eventless
response.createdbudget. Both are conceptuallyadjacent: timing/classification may decide when retirement happens, while
this PR decides whether that retirement is valid circuit evidence.
Changes
a genuine pre-response failure still records exactly one strike after its
requests have been failed and removed.
settlement path, so one failure cannot be charged twice.
lifecycle is still pre-response.
snapshot while preserving explicit pre-drain evidence from reader failures.
lifecycle evidence must not drift together again.
retirement with omitted event evidence, plus a routed
/backend-api/codex/responsesregression for idle retirement followed by onereal failure on the same hard key.
Test plan
Screenshots / output
No dashboard-visible changes and no wire-format changes.
Before:
After:
Two genuine consecutive eventless request failures still open the configured
durable cooldown.
Simplicity
variable, or dashboard surface
Checklist
inline.
CHANGELOG.mdwas not edited.