rustis 0.23.0

Redis async driver for Rust
Documentation
use crate::client::ReconnectionConfig;
use rand::{RngExt, rng};
use std::cmp;

pub(crate) struct ReconnectionState {
    config: ReconnectionConfig,
    attempts: u32,
}

impl ReconnectionState {
    pub(crate) fn new(config: ReconnectionConfig) -> Self {
        Self {
            config,
            attempts: 0,
        }
    }

    /// Reset the number of reconnection attempts.
    pub(crate) fn reset_attempts(&mut self) {
        self.attempts = 0;
    }

    /// Calculate the next delay, incrementing `attempts` in the process.
    #[expect(
        clippy::arithmetic_side_effects,
        reason = "`incr_with_max` answered `Some` on the line above, so the attempt \
                  count is at least 1."
    )]
    pub(crate) fn next_delay(&mut self) -> Option<u64> {
        match &self.config {
            ReconnectionConfig::Constant {
                delay,
                max_attempts,
                jitter,
            } => {
                self.attempts = incr_with_max(self.attempts, *max_attempts)?;
                Some(add_jitter(u64::from(*delay), *jitter))
            }
            ReconnectionConfig::Linear {
                max_delay,
                max_attempts,
                delay,
                jitter,
            } => {
                self.attempts = incr_with_max(self.attempts, *max_attempts)?;
                let delay = u64::from(*delay).saturating_mul(u64::from(self.attempts));

                Some(cmp::min(u64::from(*max_delay), add_jitter(delay, *jitter)))
            }
            ReconnectionConfig::Exponential {
                min_delay,
                max_delay,
                max_attempts,
                multiplicative_factor,
                jitter,
            } => {
                self.attempts = incr_with_max(self.attempts, *max_attempts)?;
                let delay = u64::from(*multiplicative_factor)
                    .saturating_pow(self.attempts - 1)
                    .saturating_mul(u64::from(*min_delay));

                Some(cmp::min(u64::from(*max_delay), add_jitter(delay, *jitter)))
            }
        }
    }
}

fn incr_with_max(curr: u32, max: u32) -> Option<u32> {
    if max != 0 && curr >= max {
        None
    } else {
        Some(curr.saturating_add(1))
    }
}

fn add_jitter(delay: u64, jitter: u32) -> u64 {
    if jitter == 0 {
        delay
    } else {
        delay.saturating_add(rng().random_range(0..u64::from(jitter)))
    }
}