kestrel_timer/
config.rs

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