oclock 0.1.11

Time tracking utility
Documentation
use nng::{Protocol, Socket};
use serde::de::DeserializeOwned;
use serde::Serialize;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum SrvInvocationError {
    #[error("Server error - {0}")]
    ServerError(String),
    #[error("Communication Error - {0}")]
    CommunicationError(String),
}
pub fn invoke_server<Req, Rep>(req: Req) -> Result<Rep, SrvInvocationError>
where
    Req: Serialize,
    Rep: DeserializeOwned,
{
    let socket = Socket::new(Protocol::Req0).map_err(|err| {
        SrvInvocationError::CommunicationError(format!("Error creating the req/rep socket - {err}"))
    })?;

    let pub_socket = Socket::new(Protocol::Pub0).map_err(|err| {
        SrvInvocationError::CommunicationError(format!("Error creating the pub/sub socket - {err}"))
    })?;

    socket
        .dial(crate::core::constants::SERVER_REQ_URL)
        .map_err(|err| {
            SrvInvocationError::CommunicationError(format!(
                "Error connecting to the socket - {err}"
            ))
        })?;

    let serialized_req = serde_json::to_vec(&req).map_err(|err| {
        SrvInvocationError::CommunicationError(format!("Cannot serialize command - {err}"))
    })?;

    socket.send(&serialized_req).map_err(|(_, err)| {
        SrvInvocationError::CommunicationError(format!("Cannot send request - {err}"))
    })?;

    let out = match socket.recv() {
        Ok(reply) if reply.starts_with(b"OK#") => {
            let msg = std::str::from_utf8(&reply[3..]).map_err(|err| {
                SrvInvocationError::CommunicationError(format!("Malformed reply String - {err}"))
            })?;

            let res = serde_json::from_str::<Rep>(&msg).map_err(|err| {
                SrvInvocationError::CommunicationError(format!("Cannot deserialize json - {err}"))
            });

            if let Err(err) = &res {
                log::error!("Error deserializing '{msg}' - {err}");
            }
            res
        }
        Ok(reply) if reply.starts_with(b"ERR#") => {
            log::debug!("Recv '{:?}'.", reply);

            let msg = std::str::from_utf8(&reply[4..]).map_err(|err| {
                SrvInvocationError::CommunicationError(format!("Malformed reply String - {err}"))
            })?;

            Err(SrvInvocationError::ServerError(String::from(msg)))
        }
        Ok(reply) => {
            log::error!("not recognized response {:?}", reply);
            Err(SrvInvocationError::CommunicationError(String::from(
                "Missing reply prefix",
            )))
        }
        Err(err) => {
            log::error!("Client failed to receive reply '{}'.", err);
            Err(SrvInvocationError::CommunicationError(format!(
                "Reply was not received - {err}"
            )))
        }
    };

    socket.close();

    out
}