kestrel_protocol_timer/
config.rs

1//! 定时器配置模块
2//!
3//! 提供分层的配置结构和 Builder 模式,用于配置时间轮、服务和批处理行为。
4
5use crate::error::TimerError;
6use std::time::Duration;
7
8/// 分层时间轮配置
9///
10/// 用于配置2层时间轮的参数。L0 层处理短延迟任务,L1 层处理长延迟任务。
11///
12/// # 示例
13/// ```no_run
14/// use kestrel_protocol_timer::HierarchicalWheelConfig;
15/// use std::time::Duration;
16///
17/// let config = HierarchicalWheelConfig {
18///     l0_tick_duration: Duration::from_millis(10),
19///     l0_slot_count: 512,
20///     l1_tick_duration: Duration::from_secs(1),
21///     l1_slot_count: 60,
22/// };
23/// ```
24#[derive(Debug, Clone)]
25pub struct HierarchicalWheelConfig {
26    /// L0 层(底层)每个 tick 的时间长度
27    pub l0_tick_duration: Duration,
28    /// L0 层槽位数量(必须是 2 的幂次方)
29    pub l0_slot_count: usize,
30    
31    /// L1 层(高层)每个 tick 的时间长度
32    pub l1_tick_duration: Duration,
33    /// L1 层槽位数量(必须是 2 的幂次方)
34    pub l1_slot_count: usize,
35}
36
37impl Default for HierarchicalWheelConfig {
38    fn default() -> Self {
39        Self {
40            l0_tick_duration: Duration::from_millis(10),
41            l0_slot_count: 512,
42            l1_tick_duration: Duration::from_secs(1),
43            l1_slot_count: 64,
44        }
45    }
46}
47
48/// 时间轮配置
49///
50/// 用于配置分层时间轮的参数。系统仅支持分层模式。
51///
52/// # 示例
53/// ```no_run
54/// use kestrel_protocol_timer::WheelConfig;
55/// use std::time::Duration;
56///
57/// // 使用默认配置(分层模式)
58/// let config = WheelConfig::default();
59///
60/// // 使用 Builder 自定义配置
61/// let config = WheelConfig::builder()
62///     .l0_tick_duration(Duration::from_millis(20))
63///     .l0_slot_count(1024)
64///     .l1_tick_duration(Duration::from_secs(2))
65///     .l1_slot_count(128)
66///     .build()
67///     .unwrap();
68/// ```
69#[derive(Debug, Clone)]
70pub struct WheelConfig {
71    /// 分层时间轮配置
72    pub hierarchical: HierarchicalWheelConfig,
73}
74
75impl Default for WheelConfig {
76    fn default() -> Self {
77        Self {
78            hierarchical: HierarchicalWheelConfig::default(),
79        }
80    }
81}
82
83impl WheelConfig {
84    /// 创建配置构建器
85    pub fn builder() -> WheelConfigBuilder {
86        WheelConfigBuilder::default()
87    }
88}
89
90/// 时间轮配置构建器
91#[derive(Debug, Clone)]
92pub struct WheelConfigBuilder {
93    hierarchical: HierarchicalWheelConfig,
94}
95
96impl Default for WheelConfigBuilder {
97    fn default() -> Self {
98        Self {
99            hierarchical: HierarchicalWheelConfig::default(),
100        }
101    }
102}
103
104impl WheelConfigBuilder {
105    /// 设置 L0 层 tick 时长
106    pub fn l0_tick_duration(mut self, duration: Duration) -> Self {
107        self.hierarchical.l0_tick_duration = duration;
108        self
109    }
110
111    /// 设置 L0 层槽位数量
112    pub fn l0_slot_count(mut self, count: usize) -> Self {
113        self.hierarchical.l0_slot_count = count;
114        self
115    }
116
117    /// 设置 L1 层 tick 时长
118    pub fn l1_tick_duration(mut self, duration: Duration) -> Self {
119        self.hierarchical.l1_tick_duration = duration;
120        self
121    }
122
123    /// 设置 L1 层槽位数量
124    pub fn l1_slot_count(mut self, count: usize) -> Self {
125        self.hierarchical.l1_slot_count = count;
126        self
127    }
128
129    /// 构建配置并进行验证
130    ///
131    /// # 返回
132    /// - `Ok(WheelConfig)`: 配置有效
133    /// - `Err(TimerError)`: 配置验证失败
134    ///
135    /// # 验证规则
136    /// - L0 tick 时长必须大于 0
137    /// - L1 tick 时长必须大于 0
138    /// - L0 槽位数量必须大于 0 且是 2 的幂次方
139    /// - L1 槽位数量必须大于 0 且是 2 的幂次方
140    /// - L1 tick 必须是 L0 tick 的整数倍
141    pub fn build(self) -> Result<WheelConfig, TimerError> {
142        let h = &self.hierarchical;
143        
144        // 验证 L0 层配置
145        if h.l0_tick_duration.is_zero() {
146            return Err(TimerError::InvalidConfiguration {
147                field: "l0_tick_duration".to_string(),
148                reason: "L0 层 tick 时长必须大于 0".to_string(),
149            });
150        }
151
152        if h.l0_slot_count == 0 {
153            return Err(TimerError::InvalidSlotCount {
154                slot_count: h.l0_slot_count,
155                reason: "L0 层槽位数量必须大于 0",
156            });
157        }
158
159        if !h.l0_slot_count.is_power_of_two() {
160            return Err(TimerError::InvalidSlotCount {
161                slot_count: h.l0_slot_count,
162                reason: "L0 层槽位数量必须是 2 的幂次方",
163            });
164        }
165
166        // 验证 L1 层配置
167        if h.l1_tick_duration.is_zero() {
168            return Err(TimerError::InvalidConfiguration {
169                field: "l1_tick_duration".to_string(),
170                reason: "L1 层 tick 时长必须大于 0".to_string(),
171            });
172        }
173
174        if h.l1_slot_count == 0 {
175            return Err(TimerError::InvalidSlotCount {
176                slot_count: h.l1_slot_count,
177                reason: "L1 层槽位数量必须大于 0",
178            });
179        }
180
181        if !h.l1_slot_count.is_power_of_two() {
182            return Err(TimerError::InvalidSlotCount {
183                slot_count: h.l1_slot_count,
184                reason: "L1 层槽位数量必须是 2 的幂次方",
185            });
186        }
187
188        // 验证 L1 tick 是 L0 tick 的整数倍
189        let l0_ms = h.l0_tick_duration.as_millis() as u64;
190        let l1_ms = h.l1_tick_duration.as_millis() as u64;
191        if l1_ms % l0_ms != 0 {
192            return Err(TimerError::InvalidConfiguration {
193                field: "l1_tick_duration".to_string(),
194                reason: format!(
195                    "L1 tick 时长 ({} ms) 必须是 L0 tick 时长 ({} ms) 的整数倍",
196                    l1_ms, l0_ms
197                ),
198            });
199        }
200
201        Ok(WheelConfig {
202            hierarchical: self.hierarchical,
203        })
204    }
205}
206
207/// 服务配置
208///
209/// 用于配置 TimerService 的通道容量。
210///
211/// # 示例
212/// ```no_run
213/// use kestrel_protocol_timer::ServiceConfig;
214///
215/// // 使用默认配置
216/// let config = ServiceConfig::default();
217///
218/// // 使用 Builder 自定义配置
219/// let config = ServiceConfig::builder()
220///     .command_channel_capacity(1024)
221///     .timeout_channel_capacity(2000)
222///     .build()
223///     .unwrap();
224/// ```
225#[derive(Debug, Clone)]
226pub struct ServiceConfig {
227    /// 命令通道容量
228    pub command_channel_capacity: usize,
229    /// 超时通道容量
230    pub timeout_channel_capacity: usize,
231}
232
233impl Default for ServiceConfig {
234    fn default() -> Self {
235        Self {
236            command_channel_capacity: 512,
237            timeout_channel_capacity: 1000,
238        }
239    }
240}
241
242impl ServiceConfig {
243    /// 创建配置构建器
244    pub fn builder() -> ServiceConfigBuilder {
245        ServiceConfigBuilder::default()
246    }
247}
248
249/// 服务配置构建器
250#[derive(Debug, Clone)]
251pub struct ServiceConfigBuilder {
252    command_channel_capacity: usize,
253    timeout_channel_capacity: usize,
254}
255
256impl Default for ServiceConfigBuilder {
257    fn default() -> Self {
258        let config = ServiceConfig::default();
259        Self {
260            command_channel_capacity: config.command_channel_capacity,
261            timeout_channel_capacity: config.timeout_channel_capacity,
262        }
263    }
264}
265
266impl ServiceConfigBuilder {
267    /// 设置命令通道容量
268    pub fn command_channel_capacity(mut self, capacity: usize) -> Self {
269        self.command_channel_capacity = capacity;
270        self
271    }
272
273    /// 设置超时通道容量
274    pub fn timeout_channel_capacity(mut self, capacity: usize) -> Self {
275        self.timeout_channel_capacity = capacity;
276        self
277    }
278
279    /// 构建配置并进行验证
280    ///
281    /// # 返回
282    /// - `Ok(ServiceConfig)`: 配置有效
283    /// - `Err(TimerError)`: 配置验证失败
284    ///
285    /// # 验证规则
286    /// - 所有通道容量必须大于 0
287    pub fn build(self) -> Result<ServiceConfig, TimerError> {
288        if self.command_channel_capacity == 0 {
289            return Err(TimerError::InvalidConfiguration {
290                field: "command_channel_capacity".to_string(),
291                reason: "命令通道容量必须大于 0".to_string(),
292            });
293        }
294
295        if self.timeout_channel_capacity == 0 {
296            return Err(TimerError::InvalidConfiguration {
297                field: "timeout_channel_capacity".to_string(),
298                reason: "超时通道容量必须大于 0".to_string(),
299            });
300        }
301
302        Ok(ServiceConfig {
303            command_channel_capacity: self.command_channel_capacity,
304            timeout_channel_capacity: self.timeout_channel_capacity,
305        })
306    }
307}
308
309/// 批处理配置
310///
311/// 用于配置批量操作的优化参数。
312///
313/// # 示例
314/// ```no_run
315/// use kestrel_protocol_timer::BatchConfig;
316///
317/// // 使用默认配置
318/// let config = BatchConfig::default();
319///
320/// // 自定义配置
321/// let config = BatchConfig {
322///     small_batch_threshold: 20,
323/// };
324/// ```
325#[derive(Debug, Clone)]
326pub struct BatchConfig {
327    /// 小批量阈值,用于批量取消优化
328    /// 
329    /// 当批量取消的任务数量小于等于此值时,直接逐个取消而不进行分组排序
330    pub small_batch_threshold: usize,
331}
332
333impl Default for BatchConfig {
334    fn default() -> Self {
335        Self {
336            small_batch_threshold: 10,
337        }
338    }
339}
340
341/// 顶层定时器配置
342///
343/// 组合所有子配置,提供完整的定时器系统配置。
344///
345/// # 示例
346/// ```no_run
347/// use kestrel_protocol_timer::TimerConfig;
348///
349/// // 使用默认配置
350/// let config = TimerConfig::default();
351///
352/// // 使用 Builder 自定义配置(仅配置服务参数)
353/// let config = TimerConfig::builder()
354///     .command_channel_capacity(1024)
355///     .timeout_channel_capacity(2000)
356///     .build()
357///     .unwrap();
358/// ```
359#[derive(Debug, Clone)]
360pub struct TimerConfig {
361    /// 时间轮配置
362    pub wheel: WheelConfig,
363    /// 服务配置
364    pub service: ServiceConfig,
365    /// 批处理配置
366    pub batch: BatchConfig,
367}
368
369impl Default for TimerConfig {
370    fn default() -> Self {
371        Self {
372            wheel: WheelConfig::default(),
373            service: ServiceConfig::default(),
374            batch: BatchConfig::default(),
375        }
376    }
377}
378
379impl TimerConfig {
380    /// 创建配置构建器
381    pub fn builder() -> TimerConfigBuilder {
382        TimerConfigBuilder::default()
383    }
384}
385
386/// 顶层定时器配置构建器
387#[derive(Debug)]
388pub struct TimerConfigBuilder {
389    wheel_builder: WheelConfigBuilder,
390    service_builder: ServiceConfigBuilder,
391    batch_config: BatchConfig,
392}
393
394impl Default for TimerConfigBuilder {
395    fn default() -> Self {
396        Self {
397            wheel_builder: WheelConfigBuilder::default(),
398            service_builder: ServiceConfigBuilder::default(),
399            batch_config: BatchConfig::default(),
400        }
401    }
402}
403
404impl TimerConfigBuilder {
405    /// 设置命令通道容量
406    pub fn command_channel_capacity(mut self, capacity: usize) -> Self {
407        self.service_builder = self.service_builder.command_channel_capacity(capacity);
408        self
409    }
410
411    /// 设置超时通道容量
412    pub fn timeout_channel_capacity(mut self, capacity: usize) -> Self {
413        self.service_builder = self.service_builder.timeout_channel_capacity(capacity);
414        self
415    }
416
417    /// 设置小批量阈值
418    pub fn small_batch_threshold(mut self, threshold: usize) -> Self {
419        self.batch_config.small_batch_threshold = threshold;
420        self
421    }
422
423    /// 构建配置并进行验证
424    ///
425    /// # 返回
426    /// - `Ok(TimerConfig)`: 配置有效
427    /// - `Err(TimerError)`: 配置验证失败
428    pub fn build(self) -> Result<TimerConfig, TimerError> {
429        Ok(TimerConfig {
430            wheel: self.wheel_builder.build()?,
431            service: self.service_builder.build()?,
432            batch: self.batch_config,
433        })
434    }
435}
436
437#[cfg(test)]
438mod tests {
439    use super::*;
440
441    #[test]
442    fn test_wheel_config_default() {
443        let config = WheelConfig::default();
444        assert_eq!(config.hierarchical.l0_tick_duration, Duration::from_millis(10));
445        assert_eq!(config.hierarchical.l0_slot_count, 512);
446        assert_eq!(config.hierarchical.l1_tick_duration, Duration::from_secs(1));
447        assert_eq!(config.hierarchical.l1_slot_count, 64);
448    }
449
450    #[test]
451    fn test_wheel_config_builder() {
452        let config = WheelConfig::builder()
453            .l0_tick_duration(Duration::from_millis(20))
454            .l0_slot_count(1024)
455            .l1_tick_duration(Duration::from_secs(2))
456            .l1_slot_count(128)
457            .build()
458            .unwrap();
459
460        assert_eq!(config.hierarchical.l0_tick_duration, Duration::from_millis(20));
461        assert_eq!(config.hierarchical.l0_slot_count, 1024);
462        assert_eq!(config.hierarchical.l1_tick_duration, Duration::from_secs(2));
463        assert_eq!(config.hierarchical.l1_slot_count, 128);
464    }
465
466    #[test]
467    fn test_wheel_config_validation_zero_tick() {
468        let result = WheelConfig::builder()
469            .l0_tick_duration(Duration::ZERO)
470            .build();
471
472        assert!(result.is_err());
473    }
474
475    #[test]
476    fn test_wheel_config_validation_invalid_slot_count() {
477        let result = WheelConfig::builder()
478            .l0_slot_count(100)
479            .build();
480
481        assert!(result.is_err());
482    }
483
484    #[test]
485    fn test_service_config_default() {
486        let config = ServiceConfig::default();
487        assert_eq!(config.command_channel_capacity, 512);
488        assert_eq!(config.timeout_channel_capacity, 1000);
489    }
490
491    #[test]
492    fn test_service_config_builder() {
493        let config = ServiceConfig::builder()
494            .command_channel_capacity(1024)
495            .timeout_channel_capacity(2000)
496            .build()
497            .unwrap();
498
499        assert_eq!(config.command_channel_capacity, 1024);
500        assert_eq!(config.timeout_channel_capacity, 2000);
501    }
502
503    #[test]
504    fn test_batch_config_default() {
505        let config = BatchConfig::default();
506        assert_eq!(config.small_batch_threshold, 10);
507    }
508
509    #[test]
510    fn test_timer_config_default() {
511        let config = TimerConfig::default();
512        assert_eq!(config.wheel.hierarchical.l0_slot_count, 512);
513        assert_eq!(config.service.command_channel_capacity, 512);
514        assert_eq!(config.batch.small_batch_threshold, 10);
515    }
516
517    #[test]
518    fn test_timer_config_builder() {
519        let config = TimerConfig::builder()
520            .command_channel_capacity(1024)
521            .timeout_channel_capacity(2000)
522            .small_batch_threshold(20)
523            .build()
524            .unwrap();
525
526        assert_eq!(config.service.command_channel_capacity, 1024);
527        assert_eq!(config.service.timeout_channel_capacity, 2000);
528        assert_eq!(config.batch.small_batch_threshold, 20);
529    }
530}
531