use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub enum RetryError {
MaxAttemptsExceeded { attempts: u32, max_attempts: u32 },
MaxDurationExceeded {
duration: std::time::Duration,
max_duration: std::time::Duration,
},
OperationTimeout {
duration: std::time::Duration,
timeout: std::time::Duration,
},
Aborted { reason: String },
ConfigError { message: String },
DelayStrategyError { message: String },
ExecutionError {
source: Box<dyn Error + Send + Sync>,
},
Other { message: String },
}
impl fmt::Display for RetryError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RetryError::MaxAttemptsExceeded {
attempts,
max_attempts,
} => {
write!(
f,
"Maximum attempts exceeded: {} (max: {})",
attempts, max_attempts
)
}
RetryError::MaxDurationExceeded {
duration,
max_duration,
} => {
write!(
f,
"Maximum duration exceeded: {:?} (max: {:?})",
duration, max_duration
)
}
RetryError::OperationTimeout { duration, timeout } => {
write!(
f,
"Operation timeout: execution time {:?} exceeded configured timeout {:?}",
duration, timeout
)
}
RetryError::Aborted { reason } => {
write!(f, "Operation aborted: {}", reason)
}
RetryError::ConfigError { message } => {
write!(f, "Configuration error: {}", message)
}
RetryError::DelayStrategyError { message } => {
write!(f, "Delay strategy error: {}", message)
}
RetryError::ExecutionError { source } => {
write!(f, "Execution error: {}", source)
}
RetryError::Other { message } => {
write!(f, "Other error: {}", message)
}
}
}
}
impl Error for RetryError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
RetryError::ExecutionError { source } => Some(source.as_ref()),
_ => None,
}
}
}
impl RetryError {
pub fn max_attempts_exceeded(attempts: u32, max_attempts: u32) -> Self {
RetryError::MaxAttemptsExceeded {
attempts,
max_attempts,
}
}
pub fn max_duration_exceeded(
duration: std::time::Duration,
max_duration: std::time::Duration,
) -> Self {
RetryError::MaxDurationExceeded {
duration,
max_duration,
}
}
pub fn operation_timeout(duration: std::time::Duration, timeout: std::time::Duration) -> Self {
RetryError::OperationTimeout { duration, timeout }
}
pub fn aborted(reason: &str) -> Self {
RetryError::Aborted {
reason: reason.to_string(),
}
}
pub fn config_error(message: &str) -> Self {
RetryError::ConfigError {
message: message.to_string(),
}
}
pub fn delay_strategy_error(message: &str) -> Self {
RetryError::DelayStrategyError {
message: message.to_string(),
}
}
pub fn execution_error<E: Error + Send + Sync + 'static>(error: E) -> Self {
RetryError::ExecutionError {
source: Box::new(error),
}
}
pub fn execution_error_box(error: Box<dyn Error + Send + Sync>) -> Self {
RetryError::ExecutionError { source: error }
}
pub fn other(message: &str) -> Self {
RetryError::Other {
message: message.to_string(),
}
}
}
pub type RetryResult<T> = Result<T, RetryError>;
impl From<std::io::Error> for RetryError {
fn from(error: std::io::Error) -> Self {
RetryError::ExecutionError {
source: Box::new(error),
}
}
}
impl From<Box<dyn Error + Send + Sync>> for RetryError {
fn from(error: Box<dyn Error + Send + Sync>) -> Self {
RetryError::ExecutionError { source: error }
}
}