-
Notifications
You must be signed in to change notification settings - Fork 410
fix(proxy): sweep idle bridge sessions without request traffic #1747
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
21 changes: 21 additions & 0 deletions
21
openspec/changes/sweep-idle-bridge-sessions-off-request-path/proposal.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| ## Why | ||
|
|
||
| The HTTP-bridge idle sweep (`_prune_http_bridge_sessions_locked`) is reached from exactly one place: `_get_or_create_http_bridge_session`. It is therefore request-driven, so a replica that stops receiving bridge requests never evicts its idle sessions and holds their upstream WebSockets, registry entries, and durable claims until the process restarts. | ||
|
|
||
| This is the residual leg of issue #1354. Fix (a) (#1476) already made account stream leases turn-scoped, so an idle session releases its cap slot as soon as its last turn detaches — the cap-exhaustion symptom is addressed there. What remains is resource hygiene on a quiet replica: in a multi-replica deployment, traffic moving off one replica leaves its warm sessions pinned indefinitely. | ||
|
|
||
| ## What Changes | ||
|
|
||
| - Expose the existing sweep as `prune_idle_http_bridge_sessions()`: take the bridge lock, run the same `_prune_http_bridge_sessions_locked` selection the request path uses, and schedule the pruned sessions' closes through the existing bounded close scheduler. | ||
| - Drive it from the per-replica ring heartbeat, alongside the durable-ownership reconcile that already runs there, so the sweep happens on every replica regardless of traffic, leadership, or durable-row cleanup. | ||
| - No new selection logic and no new timing: eligibility, the idle TTL that protects a session freshly handed to a request, and the close path are unchanged. | ||
|
|
||
| ## Capabilities | ||
|
|
||
| ### New Capabilities | ||
|
|
||
| None. | ||
|
|
||
| ### Modified Capabilities | ||
|
|
||
| - `sticky-session-operations`: idle bridge-session eviction no longer depends on request traffic reaching the replica. |
28 changes: 28 additions & 0 deletions
28
...p-idle-bridge-sessions-off-request-path/specs/sticky-session-operations/spec.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| ## ADDED Requirements | ||
|
|
||
| ### Requirement: Idle bridge sessions are swept without request traffic | ||
|
|
||
| The system MUST evict idle HTTP-bridge sessions on every replica independently of whether that replica is receiving bridge requests. The sweep MUST reuse the same eligibility the request path applies — a session with pending or queued work, an admission waiter, a handoff in progress, or an unanchored reservation, and a session still inside its idle TTL, MUST NOT be evicted — and MUST close evicted sessions through the existing bounded close path so a slow upstream-reader cancellation cannot block the caller. A sweep failure MUST NOT interrupt the loop that drives it, and MUST NOT prevent the other per-replica bridge upkeep that shares that loop from running. | ||
|
|
||
| #### Scenario: A replica with no bridge traffic still evicts idle sessions | ||
|
|
||
| - **GIVEN** a replica holds an idle bridge session past its idle TTL and receives no further bridge requests | ||
| - **WHEN** the sweep runs | ||
| - **THEN** the session is detached from the registry and closed, releasing its upstream WebSocket | ||
|
|
||
| #### Scenario: Sweep eligibility matches the request path | ||
|
|
||
| - **GIVEN** a session with pending work whose idle TTL has elapsed, and a session used moments ago | ||
| - **WHEN** the sweep runs | ||
| - **THEN** neither session is evicted | ||
|
|
||
| #### Scenario: One failing upkeep pass does not skip the other | ||
|
|
||
| - **GIVEN** the durable-ownership reconcile raises on a heartbeat tick | ||
| - **WHEN** that tick runs | ||
| - **THEN** the idle sweep still runs and the heartbeat loop continues | ||
|
|
||
| #### Scenario: Sweeping an empty registry does nothing | ||
|
|
||
| - **WHEN** the sweep runs with no registered bridge sessions | ||
| - **THEN** no session is closed and no cleanup work is scheduled |
18 changes: 18 additions & 0 deletions
18
openspec/changes/sweep-idle-bridge-sessions-off-request-path/tasks.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| ## 1. Sweep entry point | ||
|
|
||
| - [x] 1.1 Add `prune_idle_http_bridge_sessions()` to the bridge session-registry mixin (mixin.py is at its architecture line ratchet): take the bridge lock, reuse `_prune_http_bridge_sessions_locked`, and schedule closes via `_schedule_http_bridge_session_closes` with reason `idle_sweep` | ||
|
|
||
| ## 2. Heartbeat wiring | ||
|
|
||
| - [x] 2.1 Extract the heartbeat's bridge upkeep into `run_http_bridge_heartbeat_maintenance()` in `app/main.py` and call the sweep there beside the durable-ownership reconcile, isolating each pass so one failing cannot skip the other or stop the heartbeat | ||
|
|
||
| ## 3. Tests | ||
|
|
||
| - [x] 3.1 Idle session is evicted with no request traffic; a freshly-used session is spared | ||
| - [x] 3.2 A session with pending work is spared even past its idle TTL | ||
| - [x] 3.3 Empty registry is a no-op and schedules no cleanup task | ||
| - [x] 3.4 Heartbeat maintenance runs both passes, isolates a failing one, and tolerates a missing service — so removing the wiring fails a test rather than silently restoring the leak | ||
|
|
||
| ## 4. Spec | ||
|
|
||
| - [x] 4.1 Record that idle eviction does not depend on request traffic reaching the replica |
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
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.