Skip to content

SSH tunnel: auto-reconnect on bastion session loss #73

Description

@dasunNimantha

Problem

The SSH tunnel uses keepalives to keep idle sessions alive (#46), but a forced disconnect (network blip, NAT timeout, server-side TCP RST) still tears the tunnel down. The frontend currently just surfaces the next query failure; the user has to reopen the connection by hand even when the bastion would happily accept a fresh session.

Desired behaviour

When the russh session terminates while the connection is still in the pool, Tablio should:

  1. Mark the connection as transiently disconnected (sidebar badge turns amber).
  2. Re-open the SSH session in the background, reusing the cached ConnectionConfig and any prompt-once passphrase already in memory.
  3. Re-bind the local listener on the same port, or assign a new one and re-create the sqlx pool atomically so in-flight statements fail with a retriable error rather than silently hanging.
  4. Surface a one-line toast on success / failure.
  5. Cap retries (e.g. 3 attempts with exponential backoff) and stop retrying after the user explicitly disconnects.

Implementation notes

  • The existing SshTunnel struct is destructive on Drop. Reconnect needs a PoolManager-level wrapper that owns a Mutex<Option<SshTunnel>> plus the original ConnectionConfig.
  • sqlx pools observe the listener's local port via the rebuilt effective_config. The pool either needs to be rebuilt or have a way to swap the underlying connector.
  • For prompt-once passphrases, the in-memory passphrase is currently dropped after the first successful auth. Reconnect either has to re-prompt (UX cost) or persist the passphrase in a memory-only cache scoped to the connection lifetime.

Test plan

  • Integration test that kills the bastion mid-session and asserts the next query succeeds after reconnect.
  • Integration test that asserts a deliberate disconnect does not trigger reconnect.
  • Unit test that the retry budget is exhausted and surfaces a final error.

Tracked separately from #46 because keepalive-only is enough for the typical "NAT silently dropped my idle session" case; this issue covers the harder "the session was actually severed" case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions