fix(daemon): reconnect after the server session drops

A long-running daemon that lost its TCP connection to the server reported
session_loss "disconnected" and answered every command from the dead session
until a manual restart. Two causes:

- the daemon owned one session for its lifetime with no reconnect at all; and
- the lib's ServerActor queued a Login sent while disconnected instead of
  dialing, so even asking it to log in again never re-established a connection.

Reconnect on a dedicated thread with 1s-60s capped backoff, only for a dropped
connection to a session this process owns (never a displaced or borrowed one,
which would start a login war or fight another daemon). Let a Login through the
disconnected guard so a parked actor dials again, and bound that dial with
connect_timeout so a blackholed route cannot park the actor thread. Reset the
message reader, the queued backlog and the login verdict on disconnect so a
partial frame or stale Some(false) cannot wedge the reconnected session.
Announce the drop once per outage and re-join rooms and re-watch users on
recovery; the daemon main loop is back to save-and-stop so `daemon stop` stays
responsive during an outage. Update the session_loss event summary, which no
longer means the session is gone for good.
This commit is contained in:
Michel de Graaf
2026-09-02 11:21:19 +02:00
parent 597f378f17
commit 67d979b809
8 changed files with 436 additions and 63 deletions
+7
View File
@@ -60,6 +60,9 @@ pub trait SessionApi: Send + Sync {
}
fn listen_port(&self) -> Option<u16>;
fn session_loss(&self) -> Option<SessionLoss>;
fn relogin(&self) -> Result<bool> {
Err(soulseek_rs::SoulseekRs::NotConnected)
}
/// Search and wait out the window. Every implementation is
/// `search_with_cancel` with nothing to cancel on.
@@ -191,6 +194,10 @@ impl SessionApi for Client {
Self::session_loss(self)
}
fn relogin(&self) -> Result<bool> {
Self::login(self)
}
fn search_with_cancel(
&self,
query: &str,