Skip to content

feat(remote): exponential reconnect backoff + classified disconnect reason - #59

Merged
brettchien merged 1 commit into
mainfrom
feat/remote-reconnect-backoff-and-error-classification
Aug 15, 2026
Merged

feat(remote): exponential reconnect backoff + classified disconnect reason#59
brettchien merged 1 commit into
mainfrom
feat/remote-reconnect-backoff-and-error-classification

Conversation

@brettchien

Copy link
Copy Markdown
Contributor

Supersedes #58 (auto-closed by GitHub when its stacked base branch fix/remote-session-graceful-teardown was deleted on #57's merge). Same change, now rebased onto main (base = main).

Studio-review item 2 (reconnect backoff + error classification), 斷線原因可觀測性, and the testable slice of item 3.

What

The reconnect loop retried on a flat 5s cadence forever and surfaced every failure as a raw error string. With the gateway's small session-slot pool (max_sessions), a flapping link hammered it on a fixed beat, and the operator couldn't tell a network blip from an auth reject or the server being at capacity.

Changes

  • acp-tunnel — new pure reconnect module (unit-tested; compiles/tests without GTK so the workspace CI gate covers it):
    • backoff_delay(attempt, salt) — exponential 1→2→4→8→16s, capped 30s, + per-connection jitter.
    • DisconnectReason::classify(&str) + label()network / auth rejected / server at capacity / protocol / other.
  • remote.rs run_reconnecting — escalate backoff on consecutive fast failures; reset once a connection held ≥15s; put the classified reason in the status line (error: server at capacity, …) + Activity log. Console renders the status string as-is, so the reason surfaces with no frontend change.

Tests / verification

  • 3 new unit tests (classify the real DNS-storm string; backoff shape/cap; jitter bound) — green locally (cargo test -p acp-tunnel). Session state-machine already covered in acp-tunnel.
  • remote.rs compiles under bundle-macos CI (no GTK on the authoring box).

Not in this PR

  • Sidecar auto-restart (mcp.rs has no respawn on core crash) — separate PR.

🤖 Generated with Claude Code

…eason

The reconnect loop retried on a flat 5s cadence forever and surfaced every
failure as a raw error blob. With the gateway's handful of session slots, a
flapping link hammered it on a fixed beat, and the operator couldn't tell a
network blip from an auth reject or the server being at capacity.

- acp-tunnel: new pure `reconnect` module (unit-tested, no GTK needed):
  - `backoff_delay(attempt, salt)` — exponential 1→2→4→8→16s capped at 30s
    with per-connection jitter.
  - `DisconnectReason::classify(&str)` + `label()` — network / auth rejected
    / server at capacity / protocol / other.
- remote.rs run_reconnecting: escalate backoff on consecutive fast failures,
  reset once a connection has held ≥15s, and put the classified reason in the
  status line (e.g. "error: server at capacity") + log.

Tests: 3 new reconnect unit tests (classification + backoff shape/cap/jitter);
the Session state machine is already covered in acp-tunnel. The pure policy now
lives in the workspace-tested crate so the Tauri driver stays thin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@brettchien
brettchien merged commit c005447 into main Aug 15, 2026
2 checks passed
@brettchien
brettchien deleted the feat/remote-reconnect-backoff-and-error-classification branch August 15, 2026 08:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant