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:
@@ -15,7 +15,7 @@ use super::proto::{
|
||||
SessionLossEvent, UploadInfoDto, UploadStatusDto, UserMessageDto,
|
||||
};
|
||||
use crate::api::SessionApi;
|
||||
use soulseek_rs::DownloadStatus;
|
||||
use soulseek_rs::{DownloadStatus, SessionLoss};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::mpsc::{Receiver, SyncSender, TrySendError, sync_channel};
|
||||
@@ -175,9 +175,7 @@ struct DrainState {
|
||||
/// Last upload state reported per (user, file), so an upload that has not
|
||||
/// moved is not re-announced every tick.
|
||||
uploads: HashMap<(String, String), UploadInfoDto>,
|
||||
/// Whether the session-loss event has already gone out. It is terminal, so
|
||||
/// it is worth saying exactly once.
|
||||
reported_loss: bool,
|
||||
last_loss: Option<SessionLoss>,
|
||||
}
|
||||
|
||||
/// How long to keep asking whether a peer has answered a browse request.
|
||||
@@ -273,10 +271,12 @@ fn tick(
|
||||
publish_browses(session, hub, browses);
|
||||
publish_downloads(hub, downloads);
|
||||
|
||||
if !state.reported_loss
|
||||
&& let Some(loss) = session.session_loss()
|
||||
{
|
||||
state.reported_loss = true;
|
||||
let loss = session.session_loss();
|
||||
if loss == state.last_loss {
|
||||
return;
|
||||
}
|
||||
state.last_loss = loss;
|
||||
if let Some(loss) = loss {
|
||||
hub.publish(
|
||||
Event::SessionLoss,
|
||||
serde_json::to_value(SessionLossEvent { loss: loss.into() })
|
||||
|
||||
Reference in New Issue
Block a user