diff --git a/client/package.json b/client/package.json index cf025fcf..64a0401f 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "my-project", - "version": "0.1.40", + "version": "0.1.41", "private": true, "scripts": { "dev": "vite --host 0.0.0.0 --port 3000", diff --git a/client/src-tauri/Cargo.lock b/client/src-tauri/Cargo.lock index 2b9863e3..880cbd21 100644 --- a/client/src-tauri/Cargo.lock +++ b/client/src-tauri/Cargo.lock @@ -11839,7 +11839,7 @@ dependencies = [ [[package]] name = "xero-cli" -version = "0.1.40" +version = "0.1.41" dependencies = [ "crossterm", "flate2", @@ -11860,7 +11860,7 @@ dependencies = [ [[package]] name = "xero-desktop" -version = "0.1.40" +version = "0.1.41" dependencies = [ "arc-swap", "arrow-array", diff --git a/client/src-tauri/Cargo.toml b/client/src-tauri/Cargo.toml index 71cb8dac..931721fd 100644 --- a/client/src-tauri/Cargo.toml +++ b/client/src-tauri/Cargo.toml @@ -12,7 +12,7 @@ resolver = "2" [package] name = "xero-desktop" -version = "0.1.40" +version = "0.1.41" edition = "2021" default-run = "xero-desktop" description = "Xero desktop host" diff --git a/client/src-tauri/crates/xero-cli/Cargo.toml b/client/src-tauri/crates/xero-cli/Cargo.toml index 4d56d892..cc1ad26e 100644 --- a/client/src-tauri/crates/xero-cli/Cargo.toml +++ b/client/src-tauri/crates/xero-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "xero-cli" -version = "0.1.40" +version = "0.1.41" edition = "2021" description = "Headless Xero CLI backed by xero-agent-core" diff --git a/client/src-tauri/crates/xero-remote-bridge/src/lib.rs b/client/src-tauri/crates/xero-remote-bridge/src/lib.rs index 9079c421..64ad2ab4 100644 --- a/client/src-tauri/crates/xero-remote-bridge/src/lib.rs +++ b/client/src-tauri/crates/xero-remote-bridge/src/lib.rs @@ -713,8 +713,13 @@ impl PhoenixChannelClient { pub fn read_timeout(&mut self, timeout: Duration) -> BridgeResult> { self.set_read_timeout(Some(timeout))?; - match self.read() { - Ok(message) => Ok(Some(message)), + let read_result = self.read(); + let restore_result = self.set_read_timeout(None); + match read_result { + Ok(message) => { + restore_result?; + Ok(Some(message)) + } Err(BridgeError::WebSocket(error)) if matches!( error.as_ref(), @@ -725,6 +730,7 @@ impl PhoenixChannelClient { ) ) => { + restore_result?; Ok(None) } Err(error) => Err(error), @@ -1594,7 +1600,6 @@ where options: &DesktopBridgeLoopOptions, ) -> BridgeResult<()> { let mut connection = self.connect_desktop_channel()?; - connection.set_read_timeout(Some(options.read_timeout))?; connection.join_control()?; let mut joined_sessions = BTreeSet::new(); for session_id in initial_desktop_session_ids() { @@ -2634,6 +2639,56 @@ mod tests { server.join().expect("fake relay thread"); } + #[test] + fn phoenix_read_timeout_does_not_poison_later_join_waits() { + let listener = TcpListener::bind("127.0.0.1:0").expect("bind fake relay"); + let relay_url = format!( + "http://{}", + listener.local_addr().expect("listener address") + ); + let server = thread::spawn(move || { + let (stream, _) = listener.accept().expect("accept websocket"); + let mut socket = tungstenite::accept(stream).expect("accept websocket handshake"); + + let join_message = read_text_message(&mut socket); + let join: PhoenixMessage = serde_json::from_str(&join_message).expect("join json"); + thread::sleep(Duration::from_millis(120)); + socket + .send(Message::Text( + serde_json::to_string(&PhoenixMessage( + join.0.clone(), + join.1.clone(), + join.2.clone(), + "phx_reply".into(), + json!({"status": "ok", "response": {}}), + )) + .expect("join reply json") + .into(), + )) + .expect("send delayed join reply"); + }); + + let mut client = PhoenixChannelClient::connect( + &BridgeConfig { + relay_url, + device_name: Some("Xero Test Web".into()), + }, + "token", + PhoenixSocketKind::Web, + ) + .expect("connect fake relay"); + + assert!(client + .read_timeout(Duration::from_millis(20)) + .expect("idle read timeout") + .is_none()); + client + .join("session:desktop-1:session-1", json!({})) + .expect("delayed join reply should still be allowed"); + + server.join().expect("fake relay thread"); + } + #[test] fn bridge_forward_records_and_queues_remote_events_when_registered() { let temp = tempfile_path("bridge-forward"); diff --git a/client/src-tauri/tauri.conf.json b/client/src-tauri/tauri.conf.json index f8c5fc64..5cde45dd 100644 --- a/client/src-tauri/tauri.conf.json +++ b/client/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "productName": "Xero", "mainBinaryName": "xero-desktop", - "version": "0.1.40", + "version": "0.1.41", "identifier": "com.hyperpush.xero", "build": { "beforeDevCommand": "pnpm dev",