use std::time::Duration;
use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum HexeractError {
#[error("no handler registered for `{command_type}`")]
HandlerNotFound {
command_type: &'static str,
},
#[error("handler failed: {source}")]
HandlerFailed {
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("dispatch timed out after {elapsed:?}")]
Timeout {
elapsed: Duration,
},
#[error("dispatch error: {0}")]
Dispatch(String),
}
impl HexeractError {
pub fn handler_failed(source: impl std::error::Error + Send + Sync + 'static) -> Self {
Self::HandlerFailed {
source: Box::new(source),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn handler_not_found_display() {
let err = HexeractError::HandlerNotFound {
command_type: "RegisterUser",
};
assert_eq!(err.to_string(), "no handler registered for `RegisterUser`");
}
#[test]
fn timeout_display_shows_duration() {
let err = HexeractError::Timeout {
elapsed: Duration::from_secs(5),
};
assert!(err.to_string().contains("5s"));
}
#[test]
fn handler_failed_preserves_source() {
let original = std::io::Error::new(std::io::ErrorKind::NotFound, "file missing");
let err = HexeractError::handler_failed(original);
assert!(err.to_string().contains("handler failed"));
assert!(std::error::Error::source(&err).is_some());
}
}