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 {}