Repository navigation
fix(server): reclaim stale agent sessions on login conflict - #33
Open
vanceeasleaf wants to merge 1 commit into
Open
vanceeasleaf wants to merge 1 commit into
vanceeasleaf wants to merge 1 commit into
Conversation
A control teardown could leave the agent registry entry online after the control disappeared. Subsequent logins then failed with "agent_id ... is already online" and dashboard kick returned "client not online", requiring a server restart to recover. - allow a conflicting login to take over a stale session when its control is missing, closed, heartbeat-stale, or has no tunnels; healthy sessions with active tunnels are still rejected - clear leaked agent records and global tunnel name/port slots during takeover and dashboard kick - bound tunnel lock/close/writer/background shutdown waits so teardown always reaches agent release - show leaked online agent records as offline in the dashboard Co-Authored-By: Claude Code <[email protected]>
This branch has not been deployed
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
A failed control teardown can leave an agent record
onlineafter its control session is gone. The client then keeps retrying, but every login is rejected withagent_id [...] for user [...] is already online, and dashboard kick reportsclient not onlinebecause it only looks at live controls. Restarting the server was the only recovery. This PR makes login conflict handling reclaim such stale sessions and hardens teardown so the leak is much less likely.Root cause
Control::shutdown()held the tunnel-manager mutex while awaiting every tunnel close, with no timeout. Teardown could stall beforeagents.release()ran.register_control()rejected every same-agent conflict unconditionally, so a restarted client could never take over its own leaked record.kick_client()only searchedcontrols. When the control was absent it returnedclient not onlineand never cleared the leaked agent record.Changes
agentId.Control::shutdown()drains tunnels under a bounded lock, closes them outside the lock with a timeout, and bounds writer/background-task shutdown so it always reachesmark_finished().kick_client()now cleans a leaked agent record when no control exists, and bounds all waits.Tests
The new unit tests reproduce the leak (
stale_generation_release_leaves_agent_online) and verify recovery:force_release_clears_leaked_record_and_allows_new_sessionforce_release_does_not_clobber_newer_generationforce_release_removes_anonymous_sessionResults:
cargo test -p orbien-server --locked: 14 passed, 0 failedcargo fmt --all -- --check: cleancargo clippy -p orbien-server --locked --all-targets: no new warnings/api/v1/clientsreturns an empty listCompatibility and scope
Server-side only. No client or protocol changes; wire compatibility is unchanged.
This fixes the stale-session lockout and takeover path. A client whose tunnels are lost while its control is still healthy with zero tunnels will now be allowed to reconnect, but client-side tunnel re-registration retry remains a separate follow-up.
Related issues
This targets the server-side stale-session and stale-slot leak behind several reports: #28 (restart cannot reconnect), #27 (restart shortly after disconnect: tunnel already registered), #19 (long-running client disconnects), and #29 (dashboard stats inconsistent). It does not add client-side automatic reconnect or tunnel retry.
🤖 Generated with Claude Code