kestrel_timer/timer.rs
1pub mod handle;
2
3use crate::config::{BatchConfig, ServiceConfig, WheelConfig};
4use crate::error::TimerError;
5use crate::task::{CallbackWrapper, TaskHandle, TaskId};
6use crate::wheel::Wheel;
7use handle::{BatchHandle, BatchHandleWithCompletion, TimerHandle, TimerHandleWithCompletion};
8use parking_lot::Mutex;
9use std::sync::Arc;
10use std::time::Duration;
11use tokio::task::JoinHandle;
12use tokio::time::Instant;
13
14/// Timing Wheel Timer Manager
15///
16/// 时间轮定时器管理器
17pub struct TimerWheel {
18 /// Timing wheel instance, wrapped in `Arc<Mutex>` for multi-threaded access
19 ///
20 /// 时间轮实例,包装在 `Arc<Mutex>` 中以支持多线程访问
21 wheel: Arc<Mutex<Wheel>>,
22
23 /// Background tick loop task handle
24 ///
25 /// 后台 tick 循环任务句柄
26 tick_handle: Option<JoinHandle<()>>,
27}
28
29impl TimerWheel {
30 /// Create a new timer manager
31 ///
32 /// # Parameters
33 /// - `config`: Timing wheel configuration
34 /// - `batch_config`: Batch operation configuration
35 ///
36 /// 创建新的定时器管理器
37 ///
38 /// # 参数
39 /// - `config`: 时间轮配置
40 /// - `batch_config`: 批量操作配置
41 ///
42 /// # Examples (示例)
43 /// ```no_run
44 /// use kestrel_timer::{TimerWheel, config::WheelConfig, TimerTask, config::BatchConfig};
45 /// use std::time::Duration;
46 ///
47 /// #[tokio::main]
48 /// async fn main() {
49 /// let config = WheelConfig::builder()
50 /// .l0_tick_duration(Duration::from_millis(10))
51 /// .l0_slot_count(512)
52 /// .l1_tick_duration(Duration::from_secs(1))
53 /// .l1_slot_count(64)
54 /// .build()
55 /// .unwrap();
56 /// let timer = TimerWheel::new(config, BatchConfig::default()).unwrap();
57 ///
58 /// // Use two-step API: allocate handle first, then register
59 /// // 使用两步 API:先分配 handle,再注册
60 /// let handle = timer.allocate_handle();
61 /// let task = TimerTask::new_oneshot(Duration::from_secs(1), None);
62 /// let _timer_handle = timer.register(handle, task).unwrap();
63 /// }
64 /// ```
65 pub fn new(config: WheelConfig, batch_config: BatchConfig) -> Result<Self, TimerError> {
66 let tick_duration = config.l0_tick_duration();
67 let wheel = Wheel::new(config, batch_config)?;
68 let wheel = Arc::new(Mutex::new(wheel));
69 let wheel_clone = wheel.clone();
70
71 // Start background tick loop
72 // 启动后台 tick 循环
73 let tick_handle = tokio::spawn(async move {
74 Self::tick_loop(wheel_clone, tick_duration).await;
75 });
76
77 Ok(Self {
78 wheel,
79 tick_handle: Some(tick_handle),
80 })
81 }
82
83 /// Create timer manager with default configuration, hierarchical mode
84 /// - L0 layer tick duration: 10ms, slot count: 512
85 /// - L1 layer tick duration: 1s, slot count: 64
86 ///
87 /// # Returns
88 /// Timer manager instance
89 ///
90 /// 使用默认配置创建定时器管理器,分层模式
91 /// - L0 层 tick 持续时间:10ms,槽数量:512
92 /// - L1 层 tick 持续时间:1s,槽数量:64
93 ///
94 /// # 返回值
95 /// 定时器管理器实例
96 ///
97 /// # Examples (示例)
98 /// ```no_run
99 /// use kestrel_timer::TimerWheel;
100 ///
101 /// #[tokio::main]
102 /// async fn main() {
103 /// let timer = TimerWheel::with_defaults();
104 /// }
105 /// ```
106 pub fn with_defaults() -> Self {
107 Self::new(WheelConfig::default(), BatchConfig::default())
108 .expect("default timer wheel configuration must be valid")
109 }
110
111 /// Create TimerService bound to this timing wheel with default configuration
112 ///
113 /// # Parameters
114 /// - `service_config`: Service configuration
115 ///
116 /// # Returns
117 /// TimerService instance bound to this timing wheel
118 ///
119 /// 创建绑定到此时间轮的 TimerService,使用默认配置
120 ///
121 /// # 参数
122 /// - `service_config`: 服务配置
123 ///
124 /// # 返回值
125 /// 绑定到此时间轮的 TimerService 实例
126 ///
127 /// # Examples (示例)
128 /// ```no_run
129 /// use kestrel_timer::{TimerWheel, TimerService, CallbackWrapper, config::ServiceConfig};
130 /// use std::time::Duration;
131 ///
132 ///
133 /// #[tokio::main]
134 /// async fn main() {
135 /// let timer = TimerWheel::with_defaults();
136 /// let mut service = timer.create_service(ServiceConfig::default());
137 ///
138 /// // Use two-step API to batch schedule timers through service
139 /// // 使用两步 API 通过服务批量调度定时器
140 /// // Step 1: Allocate handles
141 /// let handles = service.allocate_handles(5);
142 ///
143 /// // Step 2: Create tasks
144 /// let tasks: Vec<_> = (0..5)
145 /// .map(|_| {
146 /// use kestrel_timer::TimerTask;
147 /// TimerTask::new_oneshot(Duration::from_millis(100), Some(CallbackWrapper::new(|| async {})))
148 /// })
149 /// .collect();
150 ///
151 /// // Step 3: Register batch
152 /// service.register_batch(handles, tasks).unwrap();
153 ///
154 /// // Receive timeout notifications
155 /// // 接收超时通知
156 /// let mut rx = service.take_receiver().unwrap();
157 /// while let Some(task_id) = rx.recv().await {
158 /// println!("Task {:?} completed", task_id);
159 /// }
160 /// }
161 /// ```
162 pub fn create_service(&self, service_config: ServiceConfig) -> crate::service::TimerService {
163 crate::service::TimerService::new(self.wheel.clone(), service_config)
164 }
165
166 /// Create TimerService bound to this timing wheel with custom configuration
167 ///
168 /// # Parameters
169 /// - `config`: Service configuration
170 ///
171 /// # Returns
172 /// TimerService instance bound to this timing wheel
173 ///
174 /// 创建绑定到此时间轮的 TimerService,使用自定义配置
175 ///
176 /// # 参数
177 /// - `config`: 服务配置
178 ///
179 /// # 返回值
180 /// 绑定到此时间轮的 TimerService 实例
181 ///
182 /// # Examples (示例)
183 /// ```no_run
184 /// use kestrel_timer::{TimerWheel, config::ServiceConfig, TimerTask};
185 /// use std::num::NonZeroUsize;
186 ///
187 /// #[tokio::main]
188 /// async fn main() {
189 /// let timer = TimerWheel::with_defaults();
190 /// let config = ServiceConfig::builder()
191 /// .command_channel_capacity(NonZeroUsize::new(1024).unwrap())
192 /// .timeout_channel_capacity(NonZeroUsize::new(2000).unwrap())
193 /// .build();
194 /// let service = timer.create_service_with_config(config);
195 /// }
196 /// ```
197 pub fn create_service_with_config(
198 &self,
199 config: ServiceConfig,
200 ) -> crate::service::TimerService {
201 crate::service::TimerService::new(self.wheel.clone(), config)
202 }
203
204 /// Allocate a handle from DeferredMap
205 ///
206 /// # Returns
207 /// A unique handle for later insertion
208 ///
209 /// # 返回值
210 /// 用于后续插入的唯一 handle
211 pub fn allocate_handle(&self) -> TaskHandle {
212 self.wheel.lock().allocate_handle()
213 }
214
215 /// Batch allocate handles from DeferredMap
216 ///
217 /// # Parameters
218 /// - `count`: Number of handles to allocate
219 ///
220 /// # Returns
221 /// Vector of unique handles for later batch insertion
222 ///
223 /// # 参数
224 /// - `count`: 要分配的 handle 数量
225 ///
226 /// # 返回值
227 /// 用于后续批量插入的唯一 handles 向量
228 pub fn allocate_handles(&self, count: usize) -> Vec<TaskHandle> {
229 self.wheel.lock().allocate_handles(count)
230 }
231
232 /// Register timer task to timing wheel (registration phase)
233 ///
234 /// # Parameters
235 /// - `task`: Task created via `create_task()`
236 ///
237 /// # Returns
238 /// Return `Ok` with a timer handle and completion receiver. Returns
239 /// `Err(TimerError::WrongWheel)` when the handle belongs to another wheel,
240 /// or `Err(TimerError::Shutdown)` when the wheel is closed.
241 ///
242 /// 注册定时器任务到时间轮 (注册阶段)
243 ///
244 /// # 参数
245 /// - `task`: 通过 `create_task()` 创建的任务
246 ///
247 /// # 返回值
248 /// 成功时返回包含完成通知接收器的定时器句柄;handle 属于其他时间轮时
249 /// 返回 `Err(TimerError::WrongWheel)`;时间轮关闭时返回
250 /// `Err(TimerError::Shutdown)`。
251 ///
252 /// # Examples (示例)
253 /// ```no_run
254 /// use kestrel_timer::{TimerWheel, TimerTask, CallbackWrapper};
255 ///
256 /// use std::time::Duration;
257 ///
258 /// #[tokio::main]
259 /// async fn main() {
260 /// let timer = TimerWheel::with_defaults();
261 ///
262 /// // Step 1: Allocate handle
263 /// let allocated_handle = timer.allocate_handle();
264 /// let task_id = allocated_handle.task_id();
265 ///
266 /// // Step 2: Create task
267 /// let task = TimerTask::new_oneshot(Duration::from_secs(1), Some(CallbackWrapper::new(|| async {
268 /// println!("Timer fired!");
269 /// })));
270 ///
271 /// // Step 3: Register task
272 /// let handle = timer.register(allocated_handle, task).unwrap();
273 ///
274 /// // Wait for timer completion
275 /// // 等待定时器完成
276 /// use kestrel_timer::CompletionReceiver;
277 /// let (rx, _handle) = handle.into_parts();
278 /// match rx {
279 /// CompletionReceiver::OneShot(receiver) => {
280 /// receiver.recv().await.unwrap();
281 /// },
282 /// _ => {}
283 /// }
284 /// }
285 /// ```
286 #[inline]
287 pub fn register(
288 &self,
289 handle: TaskHandle,
290 task: crate::task::TimerTask,
291 ) -> Result<TimerHandleWithCompletion, TimerError> {
292 let task_id = handle.task_id();
293
294 let (task, completion_rx) =
295 crate::task::TimerTaskWithCompletionNotifier::from_timer_task(task);
296
297 // Single lock to complete all operations
298 // 单次加锁完成所有操作
299 let mut wheel_guard = self.wheel.lock();
300 wheel_guard.insert_at(handle, task)?;
301
302 Ok(TimerHandleWithCompletion::new(
303 TimerHandle::new(task_id, self.wheel.clone()),
304 completion_rx,
305 ))
306 }
307
308 /// Batch register timer tasks to timing wheel (registration phase)
309 ///
310 /// # Parameters
311 /// - `handles`: Pre-allocated handles for tasks
312 /// - `tasks`: List of timer tasks
313 ///
314 /// # Returns
315 /// - `Ok(BatchHandleWithCompletion)` if all tasks are successfully registered
316 /// - `Err(TimerError::BatchLengthMismatch)` if handles and tasks lengths don't match
317 /// - `Err(TimerError::WrongWheel)` if any handle belongs to another wheel
318 /// - `Err(TimerError::Shutdown)` if the wheel is closed
319 ///
320 /// 批量注册定时器任务到时间轮 (注册阶段)
321 ///
322 /// # 参数
323 /// - `handles`: 任务的预分配 handles
324 /// - `tasks`: 定时器任务列表
325 ///
326 /// # 返回值
327 /// - `Ok(BatchHandleWithCompletion)` 如果所有任务成功注册
328 /// - `Err(TimerError::BatchLengthMismatch)` 如果 handles 和 tasks 长度不匹配
329 /// - `Err(TimerError::WrongWheel)` 如果任一 handle 属于其他时间轮
330 /// - `Err(TimerError::Shutdown)` 如果时间轮已关闭
331 ///
332 /// # Examples (示例)
333 /// ```no_run
334 /// use kestrel_timer::{TimerWheel, TimerTask};
335 /// use std::time::Duration;
336 ///
337 /// #[tokio::main]
338 /// async fn main() {
339 /// let timer = TimerWheel::with_defaults();
340 ///
341 /// // Step 1: Allocate handles
342 /// let handles = timer.allocate_handles(3);
343 ///
344 /// // Step 2: Create tasks
345 /// let tasks: Vec<_> = (0..3)
346 /// .map(|_| TimerTask::new_oneshot(Duration::from_secs(1), None))
347 /// .collect();
348 ///
349 /// // Step 3: Batch register
350 /// let batch = timer.register_batch(handles, tasks)
351 /// .expect("register_batch should succeed");
352 /// println!("Registered {} timers", batch.len());
353 /// }
354 /// ```
355 #[inline]
356 pub fn register_batch(
357 &self,
358 handles: Vec<TaskHandle>,
359 tasks: Vec<crate::task::TimerTask>,
360 ) -> Result<BatchHandleWithCompletion, TimerError> {
361 // Validate lengths match
362 if handles.len() != tasks.len() {
363 return Err(TimerError::BatchLengthMismatch {
364 handles_len: handles.len(),
365 tasks_len: tasks.len(),
366 });
367 }
368
369 let task_count = tasks.len();
370 let mut completion_rxs = Vec::with_capacity(task_count);
371 let mut task_ids = Vec::with_capacity(task_count);
372 let mut prepared_handles = Vec::with_capacity(task_count);
373 let mut prepared_tasks = Vec::with_capacity(task_count);
374
375 // Step 1: Prepare all channels and notifiers
376 for (handle, task) in handles.into_iter().zip(tasks) {
377 let task_id = handle.task_id();
378 let (task, completion_rx) =
379 crate::task::TimerTaskWithCompletionNotifier::from_timer_task(task);
380 task_ids.push(task_id);
381 completion_rxs.push(completion_rx);
382 prepared_handles.push(handle);
383 prepared_tasks.push(task);
384 }
385
386 // Step 2: Single lock, batch insert
387 {
388 let mut wheel_guard = self.wheel.lock();
389 wheel_guard.insert_batch_at(prepared_handles, prepared_tasks)?;
390 }
391
392 Ok(BatchHandleWithCompletion::new(
393 BatchHandle::new(task_ids, self.wheel.clone()),
394 completion_rxs,
395 ))
396 }
397
398 /// Cancel timer
399 ///
400 /// # Parameters
401 /// - `task_id`: Task ID
402 ///
403 /// # Returns
404 /// Returns `Ok(true)` when cancelled, `Ok(false)` when absent, or
405 /// `Err(TimerError::WrongWheel)` for an ID from another wheel.
406 ///
407 /// 取消定时器
408 ///
409 /// # 参数
410 /// - `task_id`: 任务 ID
411 ///
412 /// # 返回值
413 /// 任务存在且取消成功时返回 `Ok(true)`,任务不存在时返回 `Ok(false)`,
414 /// ID 属于其他时间轮时返回 `Err(TimerError::WrongWheel)`。
415 ///
416 /// # Examples (示例)
417 /// ```no_run
418 /// use kestrel_timer::{TimerWheel, TimerTask, CallbackWrapper};
419 ///
420 /// use std::time::Duration;
421 ///
422 /// #[tokio::main]
423 /// async fn main() {
424 /// let timer = TimerWheel::with_defaults();
425 ///
426 /// // Step 1: Allocate handle
427 /// let allocated_handle = timer.allocate_handle();
428 /// let task_id = allocated_handle.task_id();
429 ///
430 /// // Step 2: Create and register task
431 /// let task = TimerTask::new_oneshot(Duration::from_secs(10), Some(CallbackWrapper::new(|| async {
432 /// println!("Timer fired!");
433 /// })));
434 /// let _handle = timer.register(allocated_handle, task).unwrap();
435 ///
436 /// // Cancel task using task ID
437 /// // 使用任务 ID 取消任务
438 /// let cancelled = timer.cancel(task_id).unwrap();
439 /// println!("Canceled successfully: {}", cancelled);
440 /// }
441 /// ```
442 #[inline]
443 pub fn cancel(&self, task_id: TaskId) -> Result<bool, TimerError> {
444 let mut wheel = self.wheel.lock();
445 wheel.cancel(task_id)
446 }
447
448 /// Batch cancel timers
449 ///
450 /// # Parameters
451 /// - `task_ids`: List of task IDs to cancel
452 ///
453 /// # Returns
454 /// Number of successfully cancelled tasks, or
455 /// `Err(TimerError::WrongWheel)` if any ID belongs to another wheel.
456 ///
457 /// 批量取消定时器
458 ///
459 /// # 参数
460 /// - `task_ids`: 要取消的任务 ID 列表
461 ///
462 /// # 返回值
463 /// 成功取消的任务数量;如果任一 ID 属于其他时间轮则返回
464 /// `Err(TimerError::WrongWheel)`,且不修改任何任务。
465 ///
466 /// # Performance Advantages
467 /// - Batch processing reduces lock contention
468 /// - Internally optimized batch cancellation operation
469 ///
470 /// # Examples (示例)
471 /// ```no_run
472 /// use kestrel_timer::{TimerWheel, TimerTask};
473 /// use std::time::Duration;
474 ///
475 /// #[tokio::main]
476 /// async fn main() {
477 /// let timer = TimerWheel::with_defaults();
478 ///
479 /// // Create multiple timers
480 /// // 创建多个定时器
481 /// let task1 = TimerTask::new_oneshot(Duration::from_secs(10), None);
482 /// let task2 = TimerTask::new_oneshot(Duration::from_secs(10), None);
483 /// let task3 = TimerTask::new_oneshot(Duration::from_secs(10), None);
484 ///
485 /// // Allocate handles and get task IDs
486 /// let h1 = timer.allocate_handle();
487 /// let h2 = timer.allocate_handle();
488 /// let h3 = timer.allocate_handle();
489 /// let task_ids = vec![h1.task_id(), h2.task_id(), h3.task_id()];
490 ///
491 /// let _h1 = timer.register(h1, task1).unwrap();
492 /// let _h2 = timer.register(h2, task2).unwrap();
493 /// let _h3 = timer.register(h3, task3).unwrap();
494 ///
495 /// // Batch cancel
496 /// // 批量取消
497 /// let cancelled = timer.cancel_batch(&task_ids).unwrap();
498 /// println!("Canceled {} timers", cancelled);
499 /// }
500 /// ```
501 #[inline]
502 pub fn cancel_batch(&self, task_ids: &[TaskId]) -> Result<usize, TimerError> {
503 let mut wheel = self.wheel.lock();
504 wheel.cancel_batch(task_ids)
505 }
506
507 /// Postpone timer
508 ///
509 /// # Parameters
510 /// - `task_id`: Task ID to postpone
511 /// - `new_delay`: New delay duration, recalculated from current time
512 /// - `callback`: New callback function, pass `None` to keep original callback, pass `Some` to replace with new callback
513 ///
514 /// # Returns
515 /// Returns `Ok(true)` when postponed, `Ok(false)` when absent, or
516 /// `Err(TimerError::WrongWheel)` for an ID from another wheel.
517 ///
518 /// 推迟定时器
519 ///
520 /// # 参数
521 /// - `task_id`: 要推迟的任务 ID
522 /// - `new_delay`: 新的延迟时间,从当前时间重新计算
523 /// - `callback`: 新的回调函数,传递 `None` 保持原始回调,传递 `Some` 替换为新的回调
524 ///
525 /// # 返回值
526 /// 任务存在且延期成功时返回 `Ok(true)`,任务不存在时返回 `Ok(false)`,
527 /// ID 属于其他时间轮时返回 `Err(TimerError::WrongWheel)`。
528 ///
529 /// # Note
530 /// - Task ID remains unchanged after postponement
531 /// - Original completion_receiver remains valid
532 ///
533 /// # 注意
534 /// - 任务 ID 在推迟后保持不变
535 /// - 原始 completion_receiver 保持有效
536 ///
537 /// # Examples (示例)
538 ///
539 /// ## Keep original callback (保持原始回调)
540 /// ```no_run
541 /// use kestrel_timer::{TimerWheel, TimerTask, CallbackWrapper};
542 /// use std::time::Duration;
543 ///
544 ///
545 /// #[tokio::main]
546 /// async fn main() {
547 /// let timer = TimerWheel::with_defaults();
548 ///
549 /// // Allocate handle first
550 /// let allocated_handle = timer.allocate_handle();
551 /// let task_id = allocated_handle.task_id();
552 ///
553 /// let task = TimerTask::new_oneshot(Duration::from_secs(5), Some(CallbackWrapper::new(|| async {
554 /// println!("Timer fired!");
555 /// })));
556 /// let _handle = timer.register(allocated_handle, task).unwrap();
557 ///
558 /// // Postpone to 10 seconds after triggering, and keep original callback
559 /// // 推迟到 10 秒后触发,并保持原始回调
560 /// let success = timer
561 /// .postpone(task_id, Duration::from_secs(10), None)
562 /// .unwrap();
563 /// println!("Postponed successfully: {}", success);
564 /// }
565 /// ```
566 ///
567 /// ## Replace with new callback (替换为新的回调)
568 /// ```no_run
569 /// use kestrel_timer::{TimerWheel, TimerTask, CallbackWrapper};
570 /// use std::time::Duration;
571 ///
572 /// #[tokio::main]
573 /// async fn main() {
574 /// let timer = TimerWheel::with_defaults();
575 ///
576 /// // Allocate handle first
577 /// let allocated_handle = timer.allocate_handle();
578 /// let task_id = allocated_handle.task_id();
579 ///
580 /// let task = TimerTask::new_oneshot(Duration::from_secs(5), Some(CallbackWrapper::new(|| async {
581 /// println!("Original callback!");
582 /// })));
583 /// let _handle = timer.register(allocated_handle, task).unwrap();
584 ///
585 /// // Postpone to 10 seconds after triggering, and replace with new callback
586 /// // 推迟到 10 秒后触发,并替换为新的回调
587 /// let success = timer.postpone(task_id, Duration::from_secs(10), Some(CallbackWrapper::new(|| async {
588 /// println!("New callback!");
589 /// }))).unwrap();
590 /// println!("Postponed successfully: {}", success);
591 /// }
592 /// ```
593 #[inline]
594 pub fn postpone(
595 &self,
596 task_id: TaskId,
597 new_delay: Duration,
598 callback: Option<CallbackWrapper>,
599 ) -> Result<bool, TimerError> {
600 let mut wheel = self.wheel.lock();
601 wheel.postpone_at(task_id, new_delay, callback)
602 }
603
604 /// Batch postpone timers (keep original callbacks)
605 ///
606 /// # Parameters
607 /// - `updates`: List of tuples of (task ID, new delay)
608 ///
609 /// # Returns
610 /// Number of successfully postponed tasks, or
611 /// `Err(TimerError::WrongWheel)` if any ID belongs to another wheel.
612 ///
613 /// 批量推迟定时器 (保持原始回调)
614 ///
615 /// # 参数
616 /// - `updates`: (任务 ID, 新延迟) 元组列表
617 ///
618 /// # 返回值
619 /// 成功推迟的任务数量;如果任一 ID 属于其他时间轮则返回
620 /// `Err(TimerError::WrongWheel)`,且不修改任何任务。
621 ///
622 /// # Note
623 /// - This method keeps all tasks' original callbacks unchanged
624 /// - Use `postpone_batch_with_callbacks` if you need to replace callbacks
625 ///
626 /// # 注意
627 /// - 此方法保持所有任务的原始回调不变
628 /// - 如果需要替换回调,请使用 `postpone_batch_with_callbacks`
629 ///
630 /// # Performance Advantages
631 /// - Batch processing reduces lock contention
632 /// - Internally optimized batch postponement operation
633 ///
634 /// # Examples (示例)
635 /// ```no_run
636 /// use kestrel_timer::{TimerWheel, TimerTask, CallbackWrapper};
637 /// use std::time::Duration;
638 ///
639 /// #[tokio::main]
640 /// async fn main() {
641 /// let timer = TimerWheel::with_defaults();
642 ///
643 /// // Create multiple tasks with callbacks
644 /// // 创建多个带有回调的任务
645 /// let task1 = TimerTask::new_oneshot(Duration::from_secs(5), Some(CallbackWrapper::new(|| async {
646 /// println!("Task 1 fired!");
647 /// })));
648 /// let task2 = TimerTask::new_oneshot(Duration::from_secs(5), Some(CallbackWrapper::new(|| async {
649 /// println!("Task 2 fired!");
650 /// })));
651 /// let task3 = TimerTask::new_oneshot(Duration::from_secs(5), Some(CallbackWrapper::new(|| async {
652 /// println!("Task 3 fired!");
653 /// })));
654 ///
655 /// // Allocate handles and register
656 /// let h1 = timer.allocate_handle();
657 /// let h2 = timer.allocate_handle();
658 /// let h3 = timer.allocate_handle();
659 ///
660 /// let task_ids = vec![
661 /// (h1.task_id(), Duration::from_secs(10)),
662 /// (h2.task_id(), Duration::from_secs(15)),
663 /// (h3.task_id(), Duration::from_secs(20)),
664 /// ];
665 ///
666 /// timer.register(h1, task1).unwrap();
667 /// timer.register(h2, task2).unwrap();
668 /// timer.register(h3, task3).unwrap();
669 ///
670 /// // Batch postpone (keep original callbacks)
671 /// // 批量推迟 (保持原始回调)
672 /// let postponed = timer.postpone_batch(task_ids).unwrap();
673 /// println!("Postponed {} timers", postponed);
674 /// }
675 /// ```
676 #[inline]
677 pub fn postpone_batch(&self, updates: Vec<(TaskId, Duration)>) -> Result<usize, TimerError> {
678 let mut wheel = self.wheel.lock();
679 wheel.postpone_batch_at(updates)
680 }
681
682 /// Batch postpone timers (replace callbacks)
683 ///
684 /// # Parameters
685 /// - `updates`: List of tuples of (task ID, new delay, new callback)
686 ///
687 /// # Returns
688 /// Number of successfully postponed tasks, or
689 /// `Err(TimerError::WrongWheel)` if any ID belongs to another wheel.
690 ///
691 /// 批量推迟定时器 (替换回调)
692 ///
693 /// # 参数
694 /// - `updates`: (任务 ID, 新延迟, 新回调) 元组列表
695 ///
696 /// # 返回值
697 /// 成功推迟的任务数量;如果任一 ID 属于其他时间轮则返回
698 /// `Err(TimerError::WrongWheel)`,且不修改任何任务。
699 ///
700 /// # Performance Advantages
701 /// - Batch processing reduces lock contention
702 /// - Internally optimized batch postponement operation
703 ///
704 /// # Examples (示例)
705 /// ```no_run
706 /// use kestrel_timer::{TimerWheel, TimerTask, CallbackWrapper};
707 /// use std::time::Duration;
708 /// use std::sync::Arc;
709 /// use std::sync::atomic::{AtomicU32, Ordering};
710 ///
711 /// #[tokio::main]
712 /// async fn main() {
713 /// let timer = TimerWheel::with_defaults();
714 /// let counter = Arc::new(AtomicU32::new(0));
715 ///
716 /// // Create multiple timers
717 /// // 创建多个定时器
718 /// let task1 = TimerTask::new_oneshot(Duration::from_secs(5), None);
719 /// let task2 = TimerTask::new_oneshot(Duration::from_secs(5), None);
720 ///
721 /// // Allocate handles first
722 /// let h1 = timer.allocate_handle();
723 /// let h2 = timer.allocate_handle();
724 /// let id1 = h1.task_id();
725 /// let id2 = h2.task_id();
726 ///
727 /// timer.register(h1, task1).unwrap();
728 /// timer.register(h2, task2).unwrap();
729 ///
730 /// // Batch postpone and replace callbacks
731 /// // 批量推迟并替换回调
732 /// let updates: Vec<_> = vec![id1, id2]
733 /// .into_iter()
734 /// .map(|id| {
735 /// let counter = Arc::clone(&counter);
736 /// (id, Duration::from_secs(10), Some(CallbackWrapper::new(move || {
737 /// let counter = Arc::clone(&counter);
738 /// async move { counter.fetch_add(1, Ordering::SeqCst); }
739 /// })))
740 /// })
741 /// .collect();
742 /// let postponed = timer.postpone_batch_with_callbacks(updates).unwrap();
743 /// println!("Postponed {} timers", postponed);
744 /// }
745 /// ```
746 #[inline]
747 pub fn postpone_batch_with_callbacks(
748 &self,
749 updates: Vec<(TaskId, Duration, Option<CallbackWrapper>)>,
750 ) -> Result<usize, TimerError> {
751 let mut wheel = self.wheel.lock();
752 wheel.postpone_batch_with_callbacks_at(updates)
753 }
754
755 /// Core tick loop
756 ///
757 /// Background task that advances the timing wheel at regular intervals
758 ///
759 /// # Parameters
760 /// - `wheel`: Shared timing wheel instance
761 /// - `tick_duration`: Duration between ticks
762 ///
763 /// 核心 tick 循环
764 ///
765 /// 定期推进时间轮的后台任务
766 ///
767 /// # 参数
768 /// - `wheel`: 共享的时间轮实例
769 /// - `tick_duration`: tick 之间的持续时间
770 async fn tick_loop(wheel: Arc<Mutex<Wheel>>, tick_duration: Duration) {
771 let mut interval = tokio::time::interval(tick_duration);
772 interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
773
774 loop {
775 interval.tick().await;
776
777 // Advance timing wheel and get expired tasks
778 // Note: wheel.advance_at() already handles completion notifications
779 let expired_tasks = {
780 let mut wheel_guard = wheel.lock();
781 wheel_guard.advance_at(Instant::now())
782 };
783
784 // Execute callbacks for expired tasks
785 // Notifications have already been sent by wheel.advance_at()
786 for task in expired_tasks {
787 if let Some(callback) = task.callback {
788 // Spawn callback execution in a separate tokio task
789 tokio::spawn(async move {
790 let future = callback.call();
791 future.await;
792 });
793 }
794 }
795 }
796 }
797
798 /// Graceful shutdown of TimerWheel
799 ///
800 /// Cancels every task still owned by this wheel, sends `Cancelled` to
801 /// retained completion receivers, and stops the background driver. The
802 /// wheel rejects all later registrations.
803 ///
804 /// 优雅关闭 TimerWheel
805 ///
806 /// 取消此时间轮中仍存在的所有任务,向仍保留的完成接收器发送
807 /// `Cancelled`,并停止后台驱动。关闭后不再接受新的注册。
808 ///
809 /// # Examples (示例)
810 /// ```no_run
811 /// # use kestrel_timer::TimerWheel;
812 /// # #[tokio::main]
813 /// # async fn main() {
814 /// let timer = TimerWheel::with_defaults();
815 ///
816 /// // Use timer... (使用定时器...)
817 ///
818 /// timer.shutdown().await;
819 /// # }
820 /// ```
821 pub async fn shutdown(mut self) {
822 self.wheel.lock().shutdown();
823
824 if let Some(handle) = self.tick_handle.take() {
825 handle.abort();
826 let _ = handle.await;
827 }
828 }
829}
830
831/// Close the wheel and abort the background tick task when TimerWheel is dropped
832///
833/// 当 TimerWheel 被销毁时关闭时间轮并中止后台 tick 任务
834impl Drop for TimerWheel {
835 fn drop(&mut self) {
836 self.wheel.lock().shutdown();
837
838 if let Some(handle) = self.tick_handle.take() {
839 handle.abort();
840 }
841 }
842}
843
844#[cfg(test)]
845mod tests {
846 use super::*;
847 use crate::task::{CompletionReceiver, TaskCompletion, TimerTask};
848 use std::sync::atomic::{AtomicU32, Ordering};
849
850 #[tokio::test]
851 async fn test_timer_creation() {
852 let _timer = TimerWheel::with_defaults();
853 }
854
855 #[tokio::test]
856 async fn test_schedule_once() {
857 use std::sync::Arc;
858 let timer = TimerWheel::with_defaults();
859 let counter = Arc::new(AtomicU32::new(0));
860 let counter_clone = Arc::clone(&counter);
861
862 let task = TimerTask::new_oneshot(
863 Duration::from_millis(50),
864 Some(CallbackWrapper::new(move || {
865 let counter = Arc::clone(&counter_clone);
866 async move {
867 counter.fetch_add(1, Ordering::SeqCst);
868 }
869 })),
870 );
871 let allocate_handle = timer.allocate_handle();
872 let _handle = timer.register(allocate_handle, task).unwrap();
873
874 // Wait for timer to trigger
875 // 等待定时器触发
876 tokio::time::sleep(Duration::from_millis(100)).await;
877 assert_eq!(counter.load(Ordering::SeqCst), 1);
878 }
879
880 #[tokio::test]
881 async fn test_non_integral_delay_does_not_fire_early() {
882 let timer = TimerWheel::with_defaults();
883 let delay = Duration::from_millis(15);
884 let request_time = Instant::now();
885 let handle = timer
886 .register(timer.allocate_handle(), TimerTask::new_oneshot(delay, None))
887 .unwrap();
888 let (receiver, _handle) = handle.into_parts();
889
890 let completion = match receiver {
891 CompletionReceiver::OneShot(receiver) => {
892 tokio::time::timeout(Duration::from_secs(1), receiver.recv())
893 .await
894 .expect("timer should complete")
895 .expect("completion channel should remain open")
896 }
897 CompletionReceiver::Periodic(_) => {
898 panic!("expected one-shot completion receiver")
899 }
900 };
901
902 assert_eq!(completion, TaskCompletion::Called);
903 assert!(
904 request_time.elapsed() >= delay,
905 "timer fired before its requested delay"
906 );
907 }
908
909 #[tokio::test]
910 async fn test_shutdown_notifies_retained_oneshot_receiver() {
911 let timer = TimerWheel::with_defaults();
912 let task = TimerTask::new_oneshot(Duration::from_secs(10), None);
913 let (receiver, _handle) = timer
914 .register(timer.allocate_handle(), task)
915 .unwrap()
916 .into_parts();
917
918 timer.shutdown().await;
919
920 match receiver {
921 CompletionReceiver::OneShot(receiver) => {
922 assert_eq!(receiver.recv().await.unwrap(), TaskCompletion::Cancelled);
923 }
924 CompletionReceiver::Periodic(_) => panic!("expected one-shot receiver"),
925 }
926 }
927
928 #[tokio::test]
929 async fn test_drop_notifies_retained_periodic_receiver() {
930 let (receiver, _handle) = {
931 let timer = TimerWheel::with_defaults();
932 timer
933 .register(
934 timer.allocate_handle(),
935 TimerTask::new_periodic(
936 Duration::from_secs(10),
937 Duration::from_secs(10),
938 None,
939 Some(std::num::NonZeroUsize::new(1).unwrap()),
940 )
941 .unwrap(),
942 )
943 .unwrap()
944 .into_parts()
945 };
946
947 match receiver {
948 CompletionReceiver::Periodic(mut receiver) => {
949 assert_eq!(receiver.recv().await, Some(TaskCompletion::Cancelled));
950 }
951 CompletionReceiver::OneShot(_) => panic!("expected periodic receiver"),
952 }
953 }
954}