distributed_lock_redis/redlock/
helper.rs

1//! RedLock helper functions.
2
3use std::process;
4use std::sync::atomic::{AtomicU64, Ordering};
5use std::time::{SystemTime, UNIX_EPOCH};
6
7use rand::Rng;
8
9/// Helper functions for RedLock algorithm.
10pub struct RedLockHelper;
11
12impl RedLockHelper {
13    /// Checks if we have sufficient successes for majority consensus.
14    ///
15    /// For N servers, we need at least (N/2 + 1) successes.
16    pub fn has_sufficient_successes(success_count: usize, database_count: usize) -> bool {
17        let threshold = (database_count / 2) + 1;
18        success_count >= threshold
19    }
20
21    /// Checks if we have too many failures/faults to achieve majority.
22    ///
23    /// For odd N: need (N/2 + 1) failures to rule out majority.
24    /// For even N: need (N/2 + 1) failures to rule out majority.
25    pub fn has_too_many_failures_or_faults(
26        failure_or_fault_count: usize,
27        database_count: usize,
28    ) -> bool {
29        let threshold = (database_count / 2) + (database_count % 2);
30        failure_or_fault_count >= threshold
31    }
32
33    /// Generates a unique lock ID.
34    ///
35    /// Format: `{process_id}_{counter}_{random_uuid}`
36    pub fn create_lock_id() -> String {
37        static COUNTER: AtomicU64 = AtomicU64::new(0);
38        let counter = COUNTER.fetch_add(1, Ordering::Relaxed);
39
40        // Get process ID
41        let pid = process::id();
42
43        // Generate random component
44        let mut rng = rand::thread_rng();
45        let random: u64 = rng.gen();
46
47        format!("{}_{}_{:016x}", pid, counter, random)
48    }
49
50    /// Gets current time in milliseconds since Unix epoch.
51    pub fn now_millis() -> u64 {
52        SystemTime::now()
53            .duration_since(UNIX_EPOCH)
54            .unwrap()
55            .as_millis() as u64
56    }
57}