From dde4a1dffb154cca9e4e69301ccfc99cfea1b9d7 Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Wed, 11 Mar 2026 18:24:54 +0100 Subject: [PATCH] feat(servo-shell): reconnect appd WebSocket with exponential backoff run_listener() now loops forever instead of returning on first failure. Connect errors retry starting at 500ms, doubling up to 16s. On disconnect the inner loop breaks and the outer loop reconnects after the current backoff delay, then resets backoff to 500ms. QUERY_RUNNING is sent again on each reconnect to re-sync session state. --- crates/weft-servo-shell/src/appd_ws.rs | 44 ++++++++++++++++---------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/crates/weft-servo-shell/src/appd_ws.rs b/crates/weft-servo-shell/src/appd_ws.rs index d5831d7..ee4608d 100644 --- a/crates/weft-servo-shell/src/appd_ws.rs +++ b/crates/weft-servo-shell/src/appd_ws.rs @@ -20,26 +20,38 @@ pub fn spawn_appd_listener( fn run_listener(ws_port: u16, tx: mpsc::SyncSender, wake: Box) { let url = format!("ws://127.0.0.1:{ws_port}"); - let (mut ws, _) = match tungstenite::connect(url) { - Ok(p) => p, - Err(e) => { - tracing::warn!("appd WebSocket connect failed: {e}"); - return; - } - }; - - let _ = ws.send(tungstenite::Message::Text( - r#"{"type":"QUERY_RUNNING"}"#.into(), - )); + let mut backoff = std::time::Duration::from_millis(500); + const MAX_BACKOFF: std::time::Duration = std::time::Duration::from_secs(16); loop { - match ws.read() { - Ok(tungstenite::Message::Text(text)) => { - process_message(&text, &tx, &*wake); + match tungstenite::connect(&url) { + Err(e) => { + tracing::debug!("appd WebSocket connect failed: {e}; retry in {backoff:?}"); + std::thread::sleep(backoff); + backoff = (backoff * 2).min(MAX_BACKOFF); + continue; + } + Ok((mut ws, _)) => { + backoff = std::time::Duration::from_millis(500); + let _ = ws.send(tungstenite::Message::Text( + r#"{"type":"QUERY_RUNNING"}"#.into(), + )); + loop { + match ws.read() { + Ok(tungstenite::Message::Text(text)) => { + process_message(&text, &tx, &*wake); + } + Ok(_) => {} + Err(e) => { + tracing::debug!("appd WebSocket read error: {e}; reconnecting"); + break; + } + } + } } - Ok(_) => {} - Err(_) => break, } + std::thread::sleep(backoff); + backoff = (backoff * 2).min(MAX_BACKOFF); } }