use std::time::Duration;
use crate::types::{Uint, VerboseRateLimitError};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RateLimitError {
InsufficientCapacity {
acquiring: Uint,
available: Uint,
retry_after: Duration,
},
BeyondCapacity {
acquiring: Uint,
capacity: Uint,
},
ExpiredTick {
min_acceptable_tick: Uint,
},
ContentionFailure,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BuildError {
MissingArgument(&'static str),
InvalidArgument {
field: &'static str,
reason: &'static str
},
}
pub type RateLimitResult<T = ()> = Result<T, RateLimitError>;
pub type BuildResult<T> = Result<T, BuildError>;
impl RateLimitError {
pub fn from_core_error<F>(
error: VerboseRateLimitError,
tick_to_duration: F,
) -> Self
where
F: FnOnce(Uint) -> Duration,
{
match error {
VerboseRateLimitError::InsufficientCapacity {
acquiring,
available,
retry_after_ticks
} => {
RateLimitError::InsufficientCapacity {
acquiring,
available,
retry_after: tick_to_duration(retry_after_ticks),
}
}
VerboseRateLimitError::BeyondCapacity { acquiring, capacity } => {
RateLimitError::BeyondCapacity { acquiring, capacity }
}
VerboseRateLimitError::ExpiredTick { min_acceptable_tick } => {
RateLimitError::ExpiredTick { min_acceptable_tick }
}
VerboseRateLimitError::ContentionFailure => {
RateLimitError::ContentionFailure
}
}
}
}
impl std::fmt::Display for RateLimitError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RateLimitError::InsufficientCapacity { acquiring, available, retry_after } => {
write!(
f,
"Insufficient capacity: requested {}, available {}, retry after {:?}",
acquiring, available, retry_after
)
}
RateLimitError::BeyondCapacity { acquiring, capacity } => {
write!(
f,
"Request exceeds capacity: requested {}, maximum {}",
acquiring, capacity
)
}
RateLimitError::ExpiredTick { min_acceptable_tick } => {
write!(
f,
"Expired tick: minimum acceptable tick is {}",
min_acceptable_tick
)
}
RateLimitError::ContentionFailure => {
write!(f, "Rate limiter lock contention")
}
}
}
}
impl std::fmt::Display for BuildError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BuildError::MissingArgument(arg) => {
write!(f, "Missing required argument: {}", arg)
}
BuildError::InvalidArgument { field, reason } => {
write!(f, "Invalid argument '{}': {}", field, reason)
}
}
}
}
impl std::error::Error for RateLimitError {}
impl std::error::Error for BuildError {}