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:
- Mark the connection as transiently disconnected (sidebar badge turns amber).
- Re-open the SSH session in the background, reusing the cached
ConnectionConfig and any prompt-once passphrase already in memory.
- 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.
- Surface a one-line toast on success / failure.
- 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.
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:
ConnectionConfigand any prompt-once passphrase already in memory.Implementation notes
SshTunnelstruct is destructive onDrop. Reconnect needs aPoolManager-level wrapper that owns aMutex<Option<SshTunnel>>plus the originalConnectionConfig.effective_config. The pool either needs to be rebuilt or have a way to swap the underlying connector.Test plan
disconnectdoes not trigger reconnect.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.