Skip to main content

pushwire_client/
reconnect.rs

1use std::time::Duration;
2
3/// Policy controlling automatic reconnection behavior.
4#[non_exhaustive]
5#[derive(Debug, Clone)]
6pub struct ReconnectPolicy {
7    /// Whether automatic reconnection is enabled.
8    pub enabled: bool,
9    /// Initial delay before first reconnect attempt.
10    pub initial_delay: Duration,
11    /// Maximum delay between reconnect attempts.
12    pub max_delay: Duration,
13    /// Multiplier applied to delay after each failed attempt.
14    pub backoff_factor: f64,
15    /// Maximum number of retries. `None` = infinite.
16    pub max_retries: Option<u32>,
17    /// Add random jitter to delay to prevent thundering herd.
18    pub jitter: bool,
19}
20
21impl Default for ReconnectPolicy {
22    fn default() -> Self {
23        Self {
24            enabled: true,
25            initial_delay: Duration::from_millis(100),
26            max_delay: Duration::from_secs(30),
27            backoff_factor: 2.0,
28            max_retries: None,
29            jitter: true,
30        }
31    }
32}
33
34impl ReconnectPolicy {
35    /// Disabled reconnection — connection failure is permanent.
36    pub fn disabled() -> Self {
37        Self {
38            enabled: false,
39            ..Default::default()
40        }
41    }
42
43    /// Compute delay for the nth attempt (0-indexed).
44    pub fn delay_for_attempt(&self, attempt: u32) -> Duration {
45        let base = self.initial_delay.as_secs_f64() * self.backoff_factor.powi(attempt as i32);
46        let clamped = base.min(self.max_delay.as_secs_f64());
47        Duration::from_secs_f64(clamped)
48    }
49
50    /// Whether we should retry after the given number of attempts.
51    pub fn should_retry(&self, attempts: u32) -> bool {
52        self.enabled && self.max_retries.is_none_or(|max| attempts < max)
53    }
54}