rate_guard/
error.rs

1//! Error types for rate limiting operations with Duration-based retry timing.
2//!
3//! This module provides error types that convert core verbose errors to
4//! Duration-based retry timing for easy integration with async ecosystems.
5//! It also includes builder-specific errors for configuration validation.
6
7use std::time::Duration;
8use crate::types::{Uint, VerboseRateLimitError};
9
10/// Verbose error type with detailed diagnostic information and Duration-based retry timing.
11///
12/// This error type provides comprehensive information about rate limiting failures,
13/// including current state and retry timing information. The retry timing is
14/// provided as a standard Duration for easy integration with async ecosystems.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum RateLimitError {
17    /// Not enough tokens available to fulfill the request.
18    InsufficientCapacity {
19        /// Number of tokens requested in the failed operation.
20        acquiring: Uint,
21        /// Number of tokens currently available in the rate limiter.
22        available: Uint,
23        /// Duration to wait before retrying the operation.
24        retry_after: Duration,
25    },
26
27    /// The requested number of tokens exceeds the maximum capacity.
28    BeyondCapacity {
29        /// Number of tokens requested in the failed operation.
30        acquiring: Uint,
31        /// Maximum capacity of the rate limiter.
32        capacity: Uint,
33    },
34
35    /// The provided tick is older than the acceptable minimum.
36    ExpiredTick {
37        /// Minimum acceptable tick value for the rate limiter.
38        min_acceptable_tick: Uint,
39    },
40
41    /// Failed to acquire the internal lock due to contention.
42    ContentionFailure,
43}
44
45/// Error type for builder configuration validation.
46///
47/// This error occurs when attempting to build a rate limiter with incomplete
48/// or invalid configuration. All required parameters must be specified and valid
49/// before calling `build()`.
50#[derive(Debug, Clone, PartialEq, Eq)]
51pub enum BuildError {
52    /// A required argument is missing.
53    MissingArgument(&'static str),
54    /// An argument has an invalid value or invalid combination with other arguments.
55    InvalidArgument { 
56        field: &'static str, 
57        reason: &'static str 
58    },
59}
60
61/// Result type for rate limiting operations with Duration-based retry timing.
62pub type RateLimitResult<T = ()> = Result<T, RateLimitError>;
63
64/// Result type for builder operations.
65pub type BuildResult<T> = Result<T, BuildError>;
66
67impl RateLimitError {
68    /// Creates a RateLimitError from a core verbose error.
69    ///
70    /// This method converts core verbose errors to high-level errors,
71    /// with tick-to-Duration conversion using the provided converter function.
72    pub fn from_core_error<F>(
73        error: VerboseRateLimitError,
74        tick_to_duration: F,
75    ) -> Self
76    where
77        F: FnOnce(Uint) -> Duration,
78    {
79        match error {
80            VerboseRateLimitError::InsufficientCapacity { 
81                acquiring, 
82                available, 
83                retry_after_ticks 
84            } => {
85                RateLimitError::InsufficientCapacity {
86                    acquiring,
87                    available,
88                    retry_after: tick_to_duration(retry_after_ticks),
89                }
90            }
91            VerboseRateLimitError::BeyondCapacity { acquiring, capacity } => {
92                RateLimitError::BeyondCapacity { acquiring, capacity }
93            }
94            VerboseRateLimitError::ExpiredTick { min_acceptable_tick } => {
95                RateLimitError::ExpiredTick { min_acceptable_tick }
96            }
97            VerboseRateLimitError::ContentionFailure => {
98                RateLimitError::ContentionFailure
99            }
100        }
101    }
102}
103
104// Display implementations for RateLimitError
105impl std::fmt::Display for RateLimitError {
106    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107        match self {
108            RateLimitError::InsufficientCapacity { acquiring, available, retry_after } => {
109                write!(
110                    f,
111                    "Insufficient capacity: requested {}, available {}, retry after {:?}",
112                    acquiring, available, retry_after
113                )
114            }
115            RateLimitError::BeyondCapacity { acquiring, capacity } => {
116                write!(
117                    f,
118                    "Request exceeds capacity: requested {}, maximum {}",
119                    acquiring, capacity
120                )
121            }
122            RateLimitError::ExpiredTick { min_acceptable_tick } => {
123                write!(
124                    f,
125                    "Expired tick: minimum acceptable tick is {}",
126                    min_acceptable_tick
127                )
128            }
129            RateLimitError::ContentionFailure => {
130                write!(f, "Rate limiter lock contention")
131            }
132        }
133    }
134}
135
136// Display implementations for BuildError
137impl std::fmt::Display for BuildError {
138    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139        match self {
140            BuildError::MissingArgument(arg) => {
141                write!(f, "Missing required argument: {}", arg)
142            }
143            BuildError::InvalidArgument { field, reason } => {
144                write!(f, "Invalid argument '{}': {}", field, reason)
145            }
146        }
147    }
148}
149
150// Error trait implementations
151impl std::error::Error for RateLimitError {}
152impl std::error::Error for BuildError {}