//! ### Errors //! //! library error helpers and types use std::result::Result as StdResult; use tracing::warn; /// an error which can be ignored with just a warning entry pub trait IgnorableError { fn unwrap_or_warn(self, msg: &str); } impl IgnorableError for StdResult where E : std::fmt::Debug { fn unwrap_or_warn(self, msg: &str) { match self { Ok(_) => {}, Err(e) => warn!("{}: {:?}", msg, e), } } } /// an error which can be ignored with just a warning entry and returning the default value pub trait IgnorableDefaultableError { fn unwrap_or_warn_default(self, msg: &str) -> T; } impl IgnorableDefaultableError for StdResult where E : std::fmt::Display, T: Default { fn unwrap_or_warn_default(self, msg: &str) -> T { match self { Ok(x) => x, Err(e) => { warn!("{}: {}", msg, e); T::default() }, } } } /// result type for codemp errors pub type Result = StdResult; // TODO split this into specific errors for various parts of the library /// codemp error type for library issues #[derive(Debug, thiserror::Error)] pub enum Error { /// errors caused by tonic http layer #[error("tonic error (status: {status}, message: {message})")] Transport { status: String, message: String, }, /// errors caused by async channels #[error("channel error, send: {send}")] Channel { send: bool }, /// errors caused by wrong usage of library objects #[error("invalid state error: {msg}")] InvalidState { msg: String, }, /// errors caused by wrong interlocking, safe to retry #[error("deadlocked error")] Deadlocked } impl From for Error { fn from(status: tonic::Status) -> Self { Error::Transport { status: status.code().to_string(), message: status.message().to_string() } } } impl From for Error { fn from(err: tonic::transport::Error) -> Self { Error::Transport { status: tonic::Code::Unknown.to_string(), message: format!("underlying transport error: {:?}", err) } } } impl From> for Error { fn from(_value: tokio::sync::mpsc::error::SendError) -> Self { Error::Channel { send: true } } } impl From> for Error { fn from(_value: tokio::sync::watch::error::SendError) -> Self { Error::Channel { send: true } } } impl From for Error { fn from(_value: tokio::sync::broadcast::error::RecvError) -> Self { Error::Channel { send: false } } } impl From for Error { fn from(_value: tokio::sync::watch::error::RecvError) -> Self { Error::Channel { send: false } } }