lago_client/
retry.rs

1use std::time::Duration;
2
3/// Defines the retry behavior for failed requests
4///
5/// This enum controls how the client handles retry attempts when requests fail.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum RetryMode {
8    Off,
9    Standard,
10    Adaptive,
11}
12
13impl Default for RetryMode {
14    /// Returns the default retry mode (Standard)
15    ///
16    /// # Returns
17    /// `RetryMode::Standard` as the default retry behavior
18    fn default() -> Self {
19        RetryMode::Standard
20    }
21}
22
23/// Configuration settings for retry behavior
24///
25/// This struct contains all the parameters needed to configure how the client
26/// handles retry attempts, including timing, limits, and backoff strategies.
27#[derive(Debug, Clone)]
28pub struct RetryConfig {
29    pub(crate) mode: RetryMode,
30    pub(crate) max_attempts: u32,
31    pub(crate) initial_delay: Duration,
32    pub(crate) max_delay: Duration,
33    pub(crate) backoff_multiplier: f64,
34}
35
36impl RetryConfig {
37    /// Creates a new retry configuration with default settings
38    ///
39    /// # Returns
40    /// A new `RetryConfig` instance with default values
41    pub fn new() -> Self {
42        Self::default()
43    }
44
45    /// Creates a new retry configuration builder
46    ///
47    /// # Returns
48    /// A new `RetryConfigBuilder` instance for constructing custom retry settings
49    pub fn builder() -> RetryConfigBuilder {
50        RetryConfigBuilder::new()
51    }
52
53    /// Gets the retry mode
54    ///
55    /// # Returns
56    /// A reference to the current retry mode
57    pub fn mode(&self) -> &RetryMode {
58        &self.mode
59    }
60
61    /// Gets the maximum number of retry attempts
62    ///
63    /// # Returns
64    /// A reference to the maximum attempts setting
65    pub fn max_attempts(&self) -> &u32 {
66        &self.max_attempts
67    }
68
69    /// Gets the initial delay for retry attempts
70    ///
71    /// # Returns
72    /// A reference to the initial delay duration
73    pub fn initial_delay(&self) -> &Duration {
74        &self.initial_delay
75    }
76
77    /// Gets the maximum delay between retry attempts
78    ///
79    /// # Returns
80    /// A reference to the maximum delay duration
81    pub fn max_delay(&self) -> &Duration {
82        &self.max_delay
83    }
84
85    /// Calculates the delay duration for a specific retry attempt
86    ///
87    /// This method implements exponential backoff with a configurable multiplier
88    /// and enforces the maximum delay limit.
89    ///
90    /// # Arguments
91    /// * `attempt` - The attempt number (0-based)
92    ///
93    /// # Returns
94    /// The duration to wait before the next retry attempt
95    pub fn delay_for_attempt(&self, attempt: u32) -> Duration {
96        if self.mode == RetryMode::Off {
97            return Duration::from_secs(0);
98        }
99
100        let delay_secs =
101            self.initial_delay.as_secs_f64() * self.backoff_multiplier.powi(attempt as i32);
102
103        let delay = Duration::from_secs_f64(delay_secs);
104
105        if delay > self.max_delay {
106            self.max_delay
107        } else {
108            delay
109        }
110    }
111}
112
113impl Default for RetryConfig {
114    /// Creates a default retry configuration
115    ///
116    /// By default, retries are disabled (mode is Off) with conservative settings
117    /// that can be overridden when building a custom configuration.
118    fn default() -> Self {
119        Self {
120            mode: RetryMode::Off,
121            max_attempts: 1,
122            initial_delay: Duration::from_millis(100),
123            max_delay: Duration::from_secs(30),
124            backoff_multiplier: 2.0,
125        }
126    }
127}
128
129/// Builder for creating customized retry configuration instances
130///
131/// This builder allows you to configure various aspects of retry behavior
132/// such as retry mode, maximum attempts, delays, and backoff multipliers.
133#[derive(Debug, Clone)]
134pub struct RetryConfigBuilder {
135    mode: RetryMode,
136    max_attempts: u32,
137    initial_delay: Duration,
138    max_delay: Duration,
139    backoff_multiplier: f64,
140}
141
142impl RetryConfigBuilder {
143    /// Creates a new retry configuration builder with sensible defaults
144    ///
145    /// # Returns
146    /// A new `RetryConfigBuilder` instance with default retry settings
147    pub fn new() -> Self {
148        Self {
149            mode: RetryMode::Standard,
150            max_attempts: 3,
151            initial_delay: Duration::from_millis(100),
152            max_delay: Duration::from_secs(30),
153            backoff_multiplier: 2.0,
154        }
155    }
156
157    /// Sets the retry mode
158    ///
159    /// # Arguments
160    /// * `mode` - The retry mode to use
161    ///
162    /// # Returns
163    /// The builder instance for method chaining
164    pub fn mode(mut self, mode: RetryMode) -> Self {
165        self.mode = mode;
166        self
167    }
168
169    /// Sets the maximum number of retry attempts
170    ///
171    /// # Arguments
172    /// * `max_attempts` - The maximum number of retry attempts
173    ///
174    /// # Returns
175    /// The builder instance for method chaining
176    pub fn max_attempts(mut self, max_attempts: u32) -> Self {
177        self.max_attempts = max_attempts;
178        self
179    }
180
181    /// Sets the initial delay for retry attempts
182    ///
183    /// # Arguments
184    /// * `delay` - The initial delay duration
185    ///
186    /// # Returns
187    /// The builder instance for method chaining
188    pub fn initial_delay(mut self, delay: Duration) -> Self {
189        self.initial_delay = delay;
190        self
191    }
192
193    /// Sets the maximum delay between retry attempts
194    ///
195    /// # Arguments
196    /// * `delay` - The maximum delay duration
197    ///
198    /// # Returns
199    /// The builder instance for method chaining
200    pub fn max_delay(mut self, delay: Duration) -> Self {
201        self.max_delay = delay;
202        self
203    }
204
205    /// Sets the backoff multiplier for exponential backoff
206    ///
207    /// # Arguments
208    /// * `multiplier` - The multiplier to apply to delays between attempts
209    ///
210    /// # Returns
211    /// The builder instance for method chaining
212    pub fn backoff_multiplier(mut self, multiplier: f64) -> Self {
213        self.backoff_multiplier = multiplier;
214        self
215    }
216
217    /// Builds the final retry configuration instance
218    ///
219    /// # Returns
220    /// A new `RetryConfig` instance with the specified settings
221    pub fn build(self) -> RetryConfig {
222        RetryConfig {
223            mode: self.mode,
224            max_attempts: self.max_attempts,
225            initial_delay: self.initial_delay,
226            max_delay: self.max_delay,
227            backoff_multiplier: self.backoff_multiplier,
228        }
229    }
230}
231
232impl Default for RetryConfigBuilder {
233    /// Creates a default retry configuration builder
234    ///
235    /// This is equivalent to calling `RetryConfigBuilder::new()`.
236    fn default() -> Self {
237        Self::new()
238    }
239}