jup_sdk/
retry.rs

1/// Client-side retry module.
2/// Provides intelligent retry, error classification, and recovery strategies.
3use crate::types::JupiterError;
4use std::time::Duration;
5use tokio::time;
6
7/// Configuration for retry behavior.
8#[derive(Debug, Clone)]
9pub struct RetryConfig {
10    pub max_retries: u32,
11    pub initial_delay: Duration,
12    pub max_delay: Duration,
13    pub backoff_multiplier: f64,
14}
15
16impl Default for RetryConfig {
17    fn default() -> Self {
18        Self {
19            max_retries: 3,
20            initial_delay: Duration::from_millis(500),
21            max_delay: Duration::from_secs(5),
22            backoff_multiplier: 2.0,
23        }
24    }
25}
26
27/// Trait defining retry strategy behavior.
28pub trait RetryStrategy {
29    /// Determines if a retry should be attempted based on the error and attempt count.
30    ///
31    /// # Params
32    /// error - The error that occurred
33    /// attempt - The current attempt number (1-based)
34    ///
35    /// # Example
36    /// ```
37    /// # use crate::JupiterError;
38    /// # struct MyStrategy;
39    /// # impl RetryStrategy for MyStrategy {
40    /// #     fn should_retry(&self, error: &JupiterError, attempt: u32) -> bool {
41    /// #         attempt < 3 && !error.is_fatal()
42    /// #     }
43    /// #     fn get_delay(&self, attempt: u32) -> Duration {
44    /// #         Duration::from_millis(100 * attempt as u64)
45    /// #     }
46    /// # }
47    /// let strategy = MyStrategy;
48    /// let error = JupiterError::NetworkError;
49    /// assert!(strategy.should_retry(&error, 1));
50    /// ```
51    fn should_retry(&self, error: &JupiterError, attempt: u32) -> bool;
52
53    /// Calculates the delay before the next retry attempt.
54    ///
55    /// # Params
56    /// attempt - The current attempt number (1-based)
57    ///
58    /// # Example
59    /// ```
60    /// # use std::time::Duration;
61    /// # struct MyStrategy;
62    /// # impl RetryStrategy for MyStrategy {
63    /// #     fn should_retry(&self, _error: &JupiterError, _attempt: u32) -> bool { true }
64    /// #     fn get_delay(&self, attempt: u32) -> Duration {
65    /// #         Duration::from_millis(100 * attempt as u64)
66    /// #     }
67    /// # }
68    /// let strategy = MyStrategy;
69    /// assert_eq!(strategy.get_delay(1), Duration::from_millis(100));
70    /// assert_eq!(strategy.get_delay(2), Duration::from_millis(200));
71    /// ```
72    fn get_delay(&self, attempt: u32) -> Duration;
73}
74
75/// Categorizes errors for appropriate handling.
76#[derive(Debug, Clone, PartialEq)]
77pub enum ErrorCategory {
78    /// Network connectivity issues
79    Network,
80    /// Server errors (5xx status codes)
81    Server,
82    /// Rate limiting exceeded
83    RateLimit,
84    /// Client errors (4xx status codes)
85    Client,
86    /// Transaction-related errors
87    Transaction,
88    /// Unknown or unclassified errors
89    Unknown,
90}