Skip to main content

serdes_ai_retries/
strategy.rs

1//! Retry strategy trait.
2
3use crate::error::RetryableError;
4use async_trait::async_trait;
5use std::time::Duration;
6
7/// Trait for retry strategies.
8#[async_trait]
9pub trait RetryStrategy: Send + Sync {
10    /// Determine if and how long to wait before retrying.
11    ///
12    /// Returns `Some(duration)` if the operation should be retried after waiting,
13    /// or `None` if no more retries should be attempted.
14    fn should_retry(&self, error: &RetryableError, attempt: u32) -> Option<Duration>;
15
16    /// Get the maximum number of retries.
17    fn max_retries(&self) -> u32;
18
19    /// Check if retries are exhausted.
20    fn is_exhausted(&self, attempt: u32) -> bool {
21        attempt >= self.max_retries()
22    }
23}
24
25/// Strategy that never retries.
26#[derive(Debug, Clone, Copy, Default)]
27pub struct NoRetry;
28
29impl NoRetry {
30    /// Create a new no-retry strategy.
31    pub fn new() -> Self {
32        Self
33    }
34}
35
36#[async_trait]
37impl RetryStrategy for NoRetry {
38    fn should_retry(&self, _error: &RetryableError, _attempt: u32) -> Option<Duration> {
39        None
40    }
41
42    fn max_retries(&self) -> u32 {
43        0
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    #[test]
52    fn test_no_retry() {
53        let strategy = NoRetry::new();
54        let error = RetryableError::http(500, "error");
55
56        assert!(strategy.should_retry(&error, 0).is_none());
57        assert_eq!(strategy.max_retries(), 0);
58        assert!(strategy.is_exhausted(0));
59    }
60}