From ee258ac1154f20cd98a2ff6816ea78d5c308774e Mon Sep 17 00:00:00 2001 From: ryan Date: Sun, 5 Nov 2023 23:15:48 -0600 Subject: [PATCH] keyforkd: allow sending server-side error to clients --- keyforkd-client/src/lib.rs | 16 ++++++++++++++-- keyforkd/src/middleware.rs | 17 ++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/keyforkd-client/src/lib.rs b/keyforkd-client/src/lib.rs index 3ac56a1..4fad02d 100644 --- a/keyforkd-client/src/lib.rs +++ b/keyforkd-client/src/lib.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, os::unix::net::UnixStream, path::PathBuf}; use keyfork_frame::{try_decode_from, try_encode_to, DecodeError, EncodeError}; -use keyforkd_models::{Request, Response /* Error as KeyforkdError */}; +use keyforkd_models::{Request, Response, Error as KeyforkdError}; #[cfg(test)] mod tests; @@ -25,6 +25,9 @@ pub enum Error { #[error("Could not perform frame transformation: {0}")] FrameDec(#[from] DecodeError), + + #[error("Error in Keyforkd: {0}")] + Keyforkd(#[from] KeyforkdError) } pub type Result = std::result::Result; @@ -51,23 +54,32 @@ pub fn get_socket() -> Result { UnixStream::connect(&socket_path).map_err(|e| Error::Connect(e, socket_path)) } +/// A client to interact with Keyforkd. +/// +/// Upon creation, a socket is opened, and is kept open for the duration of the object's lifetime. +/// Currently, Keyforkd does not support the reuse of sockets. Attempting to reuse the socket after +/// previously using it will likely result in an error. #[derive(Debug)] pub struct Client { socket: UnixStream, } impl Client { + /// Create a new client from a given already-connected [`UnixStream`]. pub fn new(socket: UnixStream) -> Self { Self { socket } } + /// Create a new client using well-known socket locations. pub fn discover_socket() -> Result { get_socket().map(|socket| Self { socket }) } + /// Serialize and send a [`Request`] to the server, awaiting a [`Result`]. pub fn request(&mut self, req: &Request) -> Result { try_encode_to(&bincode::serialize(&req)?, &mut self.socket)?; let resp = try_decode_from(&mut self.socket)?; - bincode::deserialize(&resp).map_err(From::from) + let resp: Result = bincode::deserialize(&resp)?; + resp.map_err(From::from) } } diff --git a/keyforkd/src/middleware.rs b/keyforkd/src/middleware.rs index 2822239..a8d6cbc 100644 --- a/keyforkd/src/middleware.rs +++ b/keyforkd/src/middleware.rs @@ -59,7 +59,7 @@ where S: Service, Request: DeserializeOwned, >::Response: Serialize, - >::Error: std::error::Error, + >::Error: std::error::Error + Serialize, >::Future: Send + 'static, { type Response = Vec; @@ -86,9 +86,11 @@ where let response = self.service.call(request); Box::pin(async move { - let response = response - .await - .map_err(|e| BincodeServiceError::Call(e.to_string()))?; + let response = response.await; + #[cfg(feature = "tracing")] + if let Err(e) = &response { + tracing::error!("Error performing derivation: {e}"); + } serialize(&response).map_err(|e| BincodeServiceError::Convert(e.to_string())) }) } @@ -116,7 +118,7 @@ mod tests { struct App; - #[derive(Debug, thiserror::Error)] + #[derive(Debug, thiserror::Error, Serialize)] enum Infallible {} impl Service for App { @@ -141,7 +143,8 @@ mod tests { #[tokio::test] async fn can_serde_responses() { - let content = serialize(&Test::new()).unwrap(); + let test = Test::new(); + let content = serialize(&test).unwrap(); let mut service = ServiceBuilder::new() .layer(BincodeLayer::::default()) .service(App); @@ -152,6 +155,6 @@ mod tests { .call(content.clone()) .await .unwrap(); - assert_eq!(result, content); + assert_eq!(result, serialize(&Result::::Ok(test)).unwrap()); } }