use crate::error::{Error, Result};
use std::time::{Duration, Instant};
#[derive(Debug, Clone, Copy)]
pub enum RetryPolicy {
None,
Fixed {
max_retries: usize,
delay_ms: u64,
},
Exponential {
max_retries: usize,
initial_delay_ms: u64,
max_delay_ms: u64,
backoff_factor: f64,
},
}
impl RetryPolicy {
pub fn default_fixed() -> Self {
Self::Fixed {
max_retries: 3,
delay_ms: 1000,
}
}
pub fn default_exponential() -> Self {
Self::Exponential {
max_retries: 5,
initial_delay_ms: 100,
max_delay_ms: 10000,
backoff_factor: 2.0,
}
}
pub fn max_retries(&self) -> usize {
match self {
Self::None => 0,
Self::Fixed { max_retries, .. } => *max_retries,
Self::Exponential { max_retries, .. } => *max_retries,
}
}
pub fn delay_for_attempt(&self, attempt: usize) -> Duration {
match self {
Self::None => Duration::from_millis(0),
Self::Fixed { delay_ms, .. } => Duration::from_millis(*delay_ms),
Self::Exponential {
initial_delay_ms,
max_delay_ms,
backoff_factor,
..
} => {
let delay = (*initial_delay_ms as f64 * backoff_factor.powi(attempt as i32)) as u64;
Duration::from_millis(delay.min(*max_delay_ms))
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum FailureType {
Network,
Node,
Memory,
Timeout,
Data,
Unknown,
}
impl FailureType {
pub fn is_retriable(&self) -> bool {
match self {
Self::Network | Self::Node | Self::Timeout => true,
Self::Memory | Self::Data | Self::Unknown => false,
}
}
pub fn from_error(error: &Error) -> Self {
match error {
Error::IoError(_) => Self::Network,
Error::Timeout(_) => Self::Timeout,
Error::OutOfMemory(_) => Self::Memory,
Error::DataError(_) => Self::Data,
_ => Self::Unknown,
}
}
}
#[derive(Debug, Clone)]
pub struct FailureInfo {
pub failure_type: FailureType,
pub failure_time: Instant,
pub node_id: Option<String>,
pub error_message: String,
pub recovered: bool,
pub retry_attempts: usize,
}
impl FailureInfo {
pub fn new(failure_type: FailureType, error_message: impl Into<String>) -> Self {
Self {
failure_type,
failure_time: Instant::now(),
node_id: None,
error_message: error_message.into(),
recovered: false,
retry_attempts: 0,
}
}
pub fn with_node_id(mut self, node_id: impl Into<String>) -> Self {
self.node_id = Some(node_id.into());
self
}
pub fn mark_recovered(&mut self) {
self.recovered = true;
}
pub fn increment_retry(&mut self) {
self.retry_attempts += 1;
}
}
#[derive(Debug, Clone, Copy)]
pub enum RecoveryStrategy {
RetryQuery,
RetryFailedPartitions,
Reroute,
LocalFallback,
}