kestrel_protocol_timer/
config.rs1use crate::error::TimerError;
6use std::time::Duration;
7
8#[derive(Debug, Clone)]
28pub struct WheelConfig {
29 pub tick_duration: Duration,
31 pub slot_count: usize,
33}
34
35impl Default for WheelConfig {
36 fn default() -> Self {
37 Self {
38 tick_duration: Duration::from_millis(10),
39 slot_count: 512,
40 }
41 }
42}
43
44impl WheelConfig {
45 pub fn builder() -> WheelConfigBuilder {
47 WheelConfigBuilder::default()
48 }
49}
50
51#[derive(Debug, Clone)]
53pub struct WheelConfigBuilder {
54 tick_duration: Duration,
55 slot_count: usize,
56}
57
58impl Default for WheelConfigBuilder {
59 fn default() -> Self {
60 let config = WheelConfig::default();
61 Self {
62 tick_duration: config.tick_duration,
63 slot_count: config.slot_count,
64 }
65 }
66}
67
68impl WheelConfigBuilder {
69 pub fn tick_duration(mut self, duration: Duration) -> Self {
71 self.tick_duration = duration;
72 self
73 }
74
75 pub fn slot_count(mut self, count: usize) -> Self {
77 self.slot_count = count;
78 self
79 }
80
81 pub fn build(self) -> Result<WheelConfig, TimerError> {
91 if self.tick_duration.is_zero() {
93 return Err(TimerError::InvalidConfiguration {
94 field: "tick_duration".to_string(),
95 reason: "tick 时长必须大于 0".to_string(),
96 });
97 }
98
99 if self.slot_count == 0 {
101 return Err(TimerError::InvalidSlotCount {
102 slot_count: self.slot_count,
103 reason: "槽位数量必须大于 0",
104 });
105 }
106
107 if !self.slot_count.is_power_of_two() {
108 return Err(TimerError::InvalidSlotCount {
109 slot_count: self.slot_count,
110 reason: "槽位数量必须是 2 的幂次方",
111 });
112 }
113
114 Ok(WheelConfig {
115 tick_duration: self.tick_duration,
116 slot_count: self.slot_count,
117 })
118 }
119}
120
121#[derive(Debug, Clone)]
140pub struct ServiceConfig {
141 pub command_channel_capacity: usize,
143 pub timeout_channel_capacity: usize,
145}
146
147impl Default for ServiceConfig {
148 fn default() -> Self {
149 Self {
150 command_channel_capacity: 512,
151 timeout_channel_capacity: 1000,
152 }
153 }
154}
155
156impl ServiceConfig {
157 pub fn builder() -> ServiceConfigBuilder {
159 ServiceConfigBuilder::default()
160 }
161}
162
163#[derive(Debug, Clone)]
165pub struct ServiceConfigBuilder {
166 command_channel_capacity: usize,
167 timeout_channel_capacity: usize,
168}
169
170impl Default for ServiceConfigBuilder {
171 fn default() -> Self {
172 let config = ServiceConfig::default();
173 Self {
174 command_channel_capacity: config.command_channel_capacity,
175 timeout_channel_capacity: config.timeout_channel_capacity,
176 }
177 }
178}
179
180impl ServiceConfigBuilder {
181 pub fn command_channel_capacity(mut self, capacity: usize) -> Self {
183 self.command_channel_capacity = capacity;
184 self
185 }
186
187 pub fn timeout_channel_capacity(mut self, capacity: usize) -> Self {
189 self.timeout_channel_capacity = capacity;
190 self
191 }
192
193 pub fn build(self) -> Result<ServiceConfig, TimerError> {
202 if self.command_channel_capacity == 0 {
203 return Err(TimerError::InvalidConfiguration {
204 field: "command_channel_capacity".to_string(),
205 reason: "命令通道容量必须大于 0".to_string(),
206 });
207 }
208
209 if self.timeout_channel_capacity == 0 {
210 return Err(TimerError::InvalidConfiguration {
211 field: "timeout_channel_capacity".to_string(),
212 reason: "超时通道容量必须大于 0".to_string(),
213 });
214 }
215
216 Ok(ServiceConfig {
217 command_channel_capacity: self.command_channel_capacity,
218 timeout_channel_capacity: self.timeout_channel_capacity,
219 })
220 }
221}
222
223#[derive(Debug, Clone)]
240pub struct BatchConfig {
241 pub small_batch_threshold: usize,
245}
246
247impl Default for BatchConfig {
248 fn default() -> Self {
249 Self {
250 small_batch_threshold: 10,
251 }
252 }
253}
254
255#[derive(Debug, Clone)]
275pub struct TimerConfig {
276 pub wheel: WheelConfig,
278 pub service: ServiceConfig,
280 pub batch: BatchConfig,
282}
283
284impl Default for TimerConfig {
285 fn default() -> Self {
286 Self {
287 wheel: WheelConfig::default(),
288 service: ServiceConfig::default(),
289 batch: BatchConfig::default(),
290 }
291 }
292}
293
294impl TimerConfig {
295 pub fn builder() -> TimerConfigBuilder {
297 TimerConfigBuilder::default()
298 }
299}
300
301#[derive(Debug)]
303pub struct TimerConfigBuilder {
304 wheel_builder: WheelConfigBuilder,
305 service_builder: ServiceConfigBuilder,
306 batch_config: BatchConfig,
307}
308
309impl Default for TimerConfigBuilder {
310 fn default() -> Self {
311 Self {
312 wheel_builder: WheelConfigBuilder::default(),
313 service_builder: ServiceConfigBuilder::default(),
314 batch_config: BatchConfig::default(),
315 }
316 }
317}
318
319impl TimerConfigBuilder {
320 pub fn tick_duration(mut self, duration: Duration) -> Self {
322 self.wheel_builder = self.wheel_builder.tick_duration(duration);
323 self
324 }
325
326 pub fn slot_count(mut self, count: usize) -> Self {
328 self.wheel_builder = self.wheel_builder.slot_count(count);
329 self
330 }
331
332 pub fn command_channel_capacity(mut self, capacity: usize) -> Self {
334 self.service_builder = self.service_builder.command_channel_capacity(capacity);
335 self
336 }
337
338 pub fn timeout_channel_capacity(mut self, capacity: usize) -> Self {
340 self.service_builder = self.service_builder.timeout_channel_capacity(capacity);
341 self
342 }
343
344 pub fn small_batch_threshold(mut self, threshold: usize) -> Self {
346 self.batch_config.small_batch_threshold = threshold;
347 self
348 }
349
350 pub fn build(self) -> Result<TimerConfig, TimerError> {
356 Ok(TimerConfig {
357 wheel: self.wheel_builder.build()?,
358 service: self.service_builder.build()?,
359 batch: self.batch_config,
360 })
361 }
362}
363
364#[cfg(test)]
365mod tests {
366 use super::*;
367
368 #[test]
369 fn test_wheel_config_default() {
370 let config = WheelConfig::default();
371 assert_eq!(config.tick_duration, Duration::from_millis(10));
372 assert_eq!(config.slot_count, 512);
373 }
374
375 #[test]
376 fn test_wheel_config_builder() {
377 let config = WheelConfig::builder()
378 .tick_duration(Duration::from_millis(20))
379 .slot_count(1024)
380 .build()
381 .unwrap();
382
383 assert_eq!(config.tick_duration, Duration::from_millis(20));
384 assert_eq!(config.slot_count, 1024);
385 }
386
387 #[test]
388 fn test_wheel_config_validation_zero_tick() {
389 let result = WheelConfig::builder()
390 .tick_duration(Duration::ZERO)
391 .build();
392
393 assert!(result.is_err());
394 }
395
396 #[test]
397 fn test_wheel_config_validation_invalid_slot_count() {
398 let result = WheelConfig::builder()
399 .slot_count(100)
400 .build();
401
402 assert!(result.is_err());
403 }
404
405 #[test]
406 fn test_service_config_default() {
407 let config = ServiceConfig::default();
408 assert_eq!(config.command_channel_capacity, 512);
409 assert_eq!(config.timeout_channel_capacity, 1000);
410 }
411
412 #[test]
413 fn test_service_config_builder() {
414 let config = ServiceConfig::builder()
415 .command_channel_capacity(1024)
416 .timeout_channel_capacity(2000)
417 .build()
418 .unwrap();
419
420 assert_eq!(config.command_channel_capacity, 1024);
421 assert_eq!(config.timeout_channel_capacity, 2000);
422 }
423
424 #[test]
425 fn test_batch_config_default() {
426 let config = BatchConfig::default();
427 assert_eq!(config.small_batch_threshold, 10);
428 }
429
430 #[test]
431 fn test_timer_config_default() {
432 let config = TimerConfig::default();
433 assert_eq!(config.wheel.slot_count, 512);
434 assert_eq!(config.service.command_channel_capacity, 512);
435 assert_eq!(config.batch.small_batch_threshold, 10);
436 }
437
438 #[test]
439 fn test_timer_config_builder() {
440 let config = TimerConfig::builder()
441 .tick_duration(Duration::from_millis(20))
442 .slot_count(1024)
443 .command_channel_capacity(1024)
444 .timeout_channel_capacity(2000)
445 .small_batch_threshold(20)
446 .build()
447 .unwrap();
448
449 assert_eq!(config.wheel.tick_duration, Duration::from_millis(20));
450 assert_eq!(config.wheel.slot_count, 1024);
451 assert_eq!(config.service.command_channel_capacity, 1024);
452 assert_eq!(config.service.timeout_channel_capacity, 2000);
453 assert_eq!(config.batch.small_batch_threshold, 20);
454 }
455}
456