minerva 0.2.0

Causal ordering for distributed systems
use super::super::backoff::{BackoffStrategy, ConstantBackoff};

/// Configuration for HLC behavior.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ClockConfig {
    /// The skew above which [`ClockStats::has_concerning_skew`] returns
    /// `true`, in the time source's own units. The crate emits nothing; the
    /// caller decides what a warning means.
    pub max_skew_warning_threshold: u64,
    /// The backoff strategy used for handling contention in timestamp generation.
    pub backoff: BackoffStrategy,
}

impl Default for ClockConfig {
    /// 100 ms of skew (at nanosecond readings) before
    /// [`ClockStats::has_concerning_skew`] fires, and a constant 64-spin
    /// backoff with jitter.
    fn default() -> Self {
        Self {
            max_skew_warning_threshold: 100_000_000, // 100ms in nanoseconds
            #[cfg(feature = "rand")]
            backoff: BackoffStrategy::Constant(ConstantBackoff::new(64, Some(16))),
            #[cfg(not(feature = "rand"))]
            backoff: BackoffStrategy::Constant(ConstantBackoff::new(64, Some((1, 16)))),
        }
    }
}

/// Clock health information.
#[derive(Debug, Clone, Copy)]
pub struct ClockStats {
    /// The maximum forward clock skew observed, in nanoseconds.
    pub max_forward_skew_ns: u64,
    /// The maximum backward clock skew observed, in nanoseconds.
    pub max_backward_skew_ns: u64,
    /// The threshold (in nanoseconds) for considering clock skew concerning.
    pub skew_warning_threshold_ns: u64,
    /// The peak number of commit attempts for a single stamp: `0` before the
    /// first commit, `1` when uncontended. Above `1` means contention that
    /// backoff resolved. `LocalClock` never exceeds `1`.
    pub peak_attempts: u32,
}

impl ClockStats {
    /// Returns `true` if the maximum forward or backward skew exceeds the warning threshold.
    #[must_use]
    pub const fn has_concerning_skew(&self) -> bool {
        self.max_forward_skew_ns > self.skew_warning_threshold_ns
            || self.max_backward_skew_ns > self.skew_warning_threshold_ns
    }
}