codemp/src/errors.rs

114 lines
2.7 KiB
Rust

//! ### 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<T, E> IgnorableError for StdResult<T, E>
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<T> {
fn unwrap_or_warn_default(self, msg: &str) -> T;
}
impl<T, E> IgnorableDefaultableError<T> for StdResult<T, E>
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<T> = StdResult<T, Error>;
// 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<tonic::Status> for Error {
fn from(status: tonic::Status) -> Self {
Error::Transport {
status: status.code().to_string(),
message: status.message().to_string()
}
}
}
impl From<tonic::transport::Error> for Error {
fn from(err: tonic::transport::Error) -> Self {
Error::Transport {
status: tonic::Code::Unknown.to_string(),
message: format!("underlying transport error: {:?}", err)
}
}
}
impl<T> From<tokio::sync::mpsc::error::SendError<T>> for Error {
fn from(_value: tokio::sync::mpsc::error::SendError<T>) -> Self {
Error::Channel { send: true }
}
}
impl<T> From<tokio::sync::watch::error::SendError<T>> for Error {
fn from(_value: tokio::sync::watch::error::SendError<T>) -> Self {
Error::Channel { send: true }
}
}
impl From<tokio::sync::broadcast::error::RecvError> for Error {
fn from(_value: tokio::sync::broadcast::error::RecvError) -> Self {
Error::Channel { send: false }
}
}
impl From<tokio::sync::watch::error::RecvError> for Error {
fn from(_value: tokio::sync::watch::error::RecvError) -> Self {
Error::Channel { send: false }
}
}