Skip to main content

ntp_timer/
timer.rs

1use std::time::Instant;
2use tracing::{debug, warn};
3
4/// Core data structure for global timer management
5#[derive(Debug, Clone)]
6pub struct GlobalTimer {
7    /// Initial timestamp fetched from NTP
8    pub base_timestamp: i64,
9    /// Reference point of system clock
10    pub base_instant: Instant,
11    /// Timestamp of last NTP synchronization
12    pub last_sync_at: Instant,
13}
14
15impl GlobalTimer {
16    /// Creates a new global timer with the given NTP timestamp
17    pub fn new(initial_timestamp: i64) -> Self {
18        let base_instant = Instant::now();
19        debug!("初始化全局计时器,时间戳: {}", initial_timestamp);
20
21        Self {
22            base_timestamp: initial_timestamp,
23            base_instant,
24            last_sync_at: base_instant,
25        }
26    }
27
28    /// Gets the current timestamp via fast local calculation
29    pub fn get_current_timestamp(&self) -> i64 {
30        let elapsed_secs = self.base_instant.elapsed().as_secs() as i64;
31        self.base_timestamp + elapsed_secs
32    }
33
34    /// Detects if a clock jump occurred by comparing NTP timestamp with internal estimate
35    pub fn detect_clock_jump(&self, new_ntp_timestamp: i64, threshold: i64) -> bool {
36        let current_estimate = self.get_current_timestamp();
37        let drift = (new_ntp_timestamp - current_estimate).abs();
38
39        if drift > threshold {
40            warn!(
41                drift_secs = drift,
42                threshold_secs = threshold,
43                "检测到系统时钟跳跃"
44            );
45            true
46        } else {
47            debug!(drift_secs = drift, "系统时钟漂移在正常范围内");
48            false
49        }
50    }
51
52    /// 更新时间戳(处理时钟跳跃或漂移纠正)
53    pub fn update_timestamp(&mut self, new_timestamp: i64, is_jump: bool) {
54        self.base_timestamp = new_timestamp;
55        self.base_instant = Instant::now();
56        self.last_sync_at = self.base_instant;
57
58        if is_jump {
59            warn!("检测到系统时钟跳跃,重新初始化计时器");
60        } else {
61            debug!("基准时间戳已更新(漂移纠正)");
62        }
63    }
64
65    /// 检查是否需要进行同步
66    pub fn should_sync(&self, sync_interval: u64) -> bool {
67        self.last_sync_at.elapsed().as_secs() >= sync_interval
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74    use std::thread;
75
76    #[test]
77    fn test_timer_creation() {
78        let timer = GlobalTimer::new(1000);
79        assert_eq!(timer.base_timestamp, 1000);
80    }
81
82    #[test]
83    fn test_get_current_timestamp() {
84        let timer = GlobalTimer::new(1000);
85        thread::sleep(std::time::Duration::from_millis(100));
86        let ts = timer.get_current_timestamp();
87        assert!(ts >= 1000);
88    }
89
90    #[test]
91    fn test_detect_clock_jump() {
92        let timer = GlobalTimer::new(1000);
93        assert!(!timer.detect_clock_jump(1001, 5));
94        assert!(timer.detect_clock_jump(1010, 5));
95    }
96
97    #[test]
98    fn test_update_timestamp() {
99        let mut timer = GlobalTimer::new(1000);
100        timer.update_timestamp(2000, true);
101        assert_eq!(timer.base_timestamp, 2000);
102    }
103
104    #[test]
105    fn test_should_sync() {
106        let timer = GlobalTimer::new(1000);
107        assert!(!timer.should_sync(10));
108        thread::sleep(std::time::Duration::from_secs(1));
109        assert!(timer.should_sync(0));
110    }
111}