diff --git a/src/asynch/clients/websocket/exceptions.rs b/src/asynch/clients/websocket/exceptions.rs index 2d65beaf..f10600b7 100644 --- a/src/asynch/clients/websocket/exceptions.rs +++ b/src/asynch/clients/websocket/exceptions.rs @@ -38,8 +38,8 @@ pub enum XRPLWebSocketException { MissingRequestReceiver, #[error("Invalid message.")] InvalidMessage, - #[error("Failed to send message through channel: {0:?}")] - MessageChannelError(String), + #[error("Failed to send message through channel: the receiver was dropped")] + MessageChannelError, #[error("Failed to receive message through channel: {0:?}")] Canceled(#[from] Canceled), #[cfg(feature = "std")] diff --git a/src/asynch/clients/websocket/websocket_base.rs b/src/asynch/clients/websocket/websocket_base.rs index 84974c99..fbb525e4 100644 --- a/src/asynch/clients/websocket/websocket_base.rs +++ b/src/asynch/clients/websocket/websocket_base.rs @@ -77,9 +77,12 @@ where Some(sender) => sender, None => return Err(XRPLWebSocketException::MissingRequestSender.into()), }; + // On failure `send` hands back the message that could not be + // delivered; discard it so the raw response body is not surfaced + // into error-reporting channels. sender .send(message) - .map_err(XRPLWebSocketException::MessageChannelError)?; + .map_err(|_| XRPLWebSocketException::MessageChannelError)?; } else { self.messages.send(message).await; } @@ -106,3 +109,36 @@ where } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::asynch::clients::SingleExecutorMutex; + use embassy_futures::block_on; + + #[test] + fn handle_message_routes_response_to_waiting_request() { + let mut base = WebsocketBase::::new(); + block_on(async { + base.setup_request_future("1".to_string()).await; + base.handle_message(r#"{"id":"1","result":{}}"#.to_string()) + .await + .unwrap(); + let received = base.try_recv_request("1".to_string()).await.unwrap(); + assert_eq!(received, Some(r#"{"id":"1","result":{}}"#.to_string())); + }); + } + + #[test] + fn unmatched_message_is_buffered_for_pop() { + let mut base = WebsocketBase::::new(); + block_on(async { + // No request is registered, so the message falls through to the + // general message channel rather than a request receiver. + base.handle_message(r#"{"result":{}}"#.to_string()) + .await + .unwrap(); + assert_eq!(base.pop_message().await, r#"{"result":{}}"#.to_string()); + }); + } +}