Skip to main content

ntp_timer/
config.rs

1use serde::{Deserialize, Serialize};
2
3/// Configuration for NTP timer
4///
5/// Supports builder pattern for easy customization
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Config {
8    /// Background synchronization interval in seconds (default: 600)
9    pub sync_interval_secs: u64,
10
11    /// Clock jump detection threshold in seconds (default: 5)
12    pub clock_jump_threshold_secs: i64,
13
14    /// List of NTP servers to query
15    pub ntp_servers: Vec<String>,
16
17    /// Maximum retry attempts (default: 3)
18    pub max_retries: usize,
19
20    /// Socket timeout in seconds (default: 5)
21    pub socket_timeout_secs: u64,
22}
23
24impl Default for Config {
25    fn default() -> Self {
26        Self {
27            sync_interval_secs: 600,
28            clock_jump_threshold_secs: 5,
29            ntp_servers: vec![
30                "ntp.ntsc.ac.cn".to_string(),
31                "time1.ntsc.ac.cn".to_string(),
32                "time2.ntsc.ac.cn".to_string(),
33            ],
34            max_retries: 3,
35            socket_timeout_secs: 5,
36        }
37    }
38}
39
40impl Config {
41    /// Creates a new configuration with default values
42    pub fn new() -> Self {
43        Self::default()
44    }
45
46    /// Sets the background synchronization interval
47    pub fn with_sync_interval(mut self, secs: u64) -> Self {
48        self.sync_interval_secs = secs;
49        self
50    }
51
52    /// Sets the clock jump detection threshold
53    pub fn with_jump_threshold(mut self, secs: i64) -> Self {
54        self.clock_jump_threshold_secs = secs;
55        self
56    }
57
58    /// 设置 NTP 服务器列表
59    pub fn with_ntp_servers(mut self, servers: Vec<String>) -> Self {
60        self.ntp_servers = servers;
61        self
62    }
63
64    /// 设置最大重试次数
65    pub fn with_max_retries(mut self, retries: usize) -> Self {
66        self.max_retries = retries;
67        self
68    }
69
70    /// 设置套接字超时
71    pub fn with_socket_timeout(mut self, secs: u64) -> Self {
72        self.socket_timeout_secs = secs;
73        self
74    }
75
76    /// 验证配置合法性
77    pub fn validate(&self) -> Result<(), String> {
78        if self.sync_interval_secs == 0 {
79            return Err("同步间隔必须 > 0".to_string());
80        }
81        if self.clock_jump_threshold_secs < 0 {
82            return Err("时钟跳跃阈值必须 >= 0".to_string());
83        }
84        if self.ntp_servers.is_empty() {
85            return Err("NTP 服务器列表不能为空".to_string());
86        }
87        if self.max_retries == 0 {
88            return Err("最大重试次数必须 > 0".to_string());
89        }
90        if self.socket_timeout_secs == 0 {
91            return Err("套接字超时必须 > 0".to_string());
92        }
93        Ok(())
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn test_default_config() {
103        let config = Config::default();
104        assert_eq!(config.sync_interval_secs, 600);
105        assert_eq!(config.clock_jump_threshold_secs, 5);
106        assert_eq!(config.max_retries, 3);
107        assert_eq!(config.socket_timeout_secs, 5);
108    }
109
110    #[test]
111    fn test_builder_pattern() {
112        let config = Config::new()
113            .with_sync_interval(300)
114            .with_jump_threshold(3)
115            .with_max_retries(5);
116
117        assert_eq!(config.sync_interval_secs, 300);
118        assert_eq!(config.clock_jump_threshold_secs, 3);
119        assert_eq!(config.max_retries, 5);
120    }
121
122    #[test]
123    fn test_config_validation() {
124        let config = Config::default();
125        assert!(config.validate().is_ok());
126
127        let invalid = Config {
128            sync_interval_secs: 0,
129            ..Default::default()
130        };
131        assert!(invalid.validate().is_err());
132    }
133}