Distinguish read and deser errors in engine websocket
Fixes https://github.com/KittyCAD/modeling-app/issues/2639
This commit is contained in:
		| @ -40,23 +40,54 @@ pub struct TcpRead { | ||||
|     stream: futures::stream::SplitStream<tokio_tungstenite::WebSocketStream<reqwest::Upgraded>>, | ||||
| } | ||||
|  | ||||
| /// Occurs when client couldn't read from the WebSocket to the engine. | ||||
| // #[derive(Debug)] | ||||
| pub enum WebSocketReadError { | ||||
|     /// Could not read a message due to WebSocket errors. | ||||
|     Read(tokio_tungstenite::tungstenite::Error), | ||||
|     /// WebSocket message didn't contain a valid message that the KCL Executor could parse. | ||||
|     Deser(anyhow::Error), | ||||
| } | ||||
|  | ||||
| impl From<anyhow::Error> for WebSocketReadError { | ||||
|     fn from(e: anyhow::Error) -> Self { | ||||
|         Self::Deser(e) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl TcpRead { | ||||
|     pub async fn read(&mut self) -> Result<WebSocketResponse> { | ||||
|     pub async fn read(&mut self) -> std::result::Result<WebSocketResponse, WebSocketReadError> { | ||||
|         let Some(msg) = self.stream.next().await else { | ||||
|             anyhow::bail!("Failed to read from websocket"); | ||||
|             return Err(anyhow::anyhow!("Failed to read from WebSocket").into()); | ||||
|         }; | ||||
|         let msg: WebSocketResponse = match msg? { | ||||
|             WsMsg::Text(text) => serde_json::from_str(&text)?, | ||||
|             WsMsg::Binary(bin) => bson::from_slice(&bin)?, | ||||
|             other => anyhow::bail!("Unexpected websocket message from server: {}", other), | ||||
|         let msg = match msg { | ||||
|             Ok(msg) => msg, | ||||
|             Err(e) if matches!(e, tokio_tungstenite::tungstenite::Error::Protocol(_)) => { | ||||
|                 return Err(WebSocketReadError::Read(e)) | ||||
|             } | ||||
|             Err(e) => return Err(anyhow::anyhow!("Error reading from engine's WebSocket: {e}").into()), | ||||
|         }; | ||||
|         let msg: WebSocketResponse = match msg { | ||||
|             WsMsg::Text(text) => serde_json::from_str(&text) | ||||
|                 .map_err(anyhow::Error::from) | ||||
|                 .map_err(WebSocketReadError::from)?, | ||||
|             WsMsg::Binary(bin) => bson::from_slice(&bin) | ||||
|                 .map_err(anyhow::Error::from) | ||||
|                 .map_err(WebSocketReadError::from)?, | ||||
|             other => return Err(anyhow::anyhow!("Unexpected WebSocket message from engine API: {other}").into()), | ||||
|         }; | ||||
|         Ok(msg) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct TcpReadHandle { | ||||
|     handle: Arc<tokio::task::JoinHandle<Result<()>>>, | ||||
|     handle: Arc<tokio::task::JoinHandle<Result<(), WebSocketReadError>>>, | ||||
| } | ||||
|  | ||||
| impl std::fmt::Debug for TcpReadHandle { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!(f, "TcpReadHandle") | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Drop for TcpReadHandle { | ||||
| @ -150,14 +181,17 @@ impl EngineConnection { | ||||
|                 match tcp_read.read().await { | ||||
|                     Ok(ws_resp) => { | ||||
|                         for e in ws_resp.errors.iter().flatten() { | ||||
|                             println!("got error message: {e}"); | ||||
|                             println!("got error message: {} {}", e.error_code, e.message); | ||||
|                         } | ||||
|                         if let Some(id) = ws_resp.request_id { | ||||
|                             responses_clone.insert(id, ws_resp.clone()); | ||||
|                         } | ||||
|                     } | ||||
|                     Err(e) => { | ||||
|                         println!("got ws error: {:?}", e); | ||||
|                         match &e { | ||||
|                             WebSocketReadError::Read(e) => eprintln!("could not read from WS: {:?}", e), | ||||
|                             WebSocketReadError::Deser(e) => eprintln!("could not deserialize msg from WS: {:?}", e), | ||||
|                         } | ||||
|                         *socket_health_tcp_read.lock().unwrap() = SocketHealth::Inactive; | ||||
|                         return Err(e); | ||||
|                     } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user