qubit_executor/schedule/scheduled_executor_service.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use std::time::{
11 Duration,
12 Instant,
13};
14
15use qubit_function::{
16 Callable,
17 Runnable,
18};
19
20use crate::service::{
21 ExecutorService,
22 SubmissionError,
23};
24
25/// Managed executor service with delayed and instant-based submission support.
26///
27/// `ScheduledExecutorService` extends [`ExecutorService`] with per-task timing.
28/// A normal `submit` call is an immediate submission; `schedule` and
29/// `schedule_at` accept work now but delay the task start until the requested
30/// time. Successful submission only means the service accepted the scheduled
31/// task. Task success, failure, panic, or cancellation is observed through the
32/// returned tracked handle.
33pub trait ScheduledExecutorService: ExecutorService {
34 /// Schedules a runnable task to start after the supplied delay.
35 ///
36 /// # Parameters
37 ///
38 /// * `delay` - Minimum delay before the task becomes runnable.
39 /// * `task` - Runnable to execute after the delay elapses.
40 ///
41 /// # Returns
42 ///
43 /// A tracked handle for observing or cancelling the scheduled task.
44 ///
45 /// # Errors
46 ///
47 /// Returns [`SubmissionError`] when the service refuses the task before
48 /// accepting it.
49 #[inline]
50 fn schedule<T, E>(
51 &self,
52 delay: Duration,
53 task: T,
54 ) -> Result<Self::TrackedHandle<(), E>, SubmissionError>
55 where
56 T: Runnable<E> + Send + 'static,
57 E: Send + 'static,
58 {
59 let mut task = task;
60 self.schedule_callable(delay, move || task.run())
61 }
62
63 /// Schedules a callable task to start after the supplied delay.
64 ///
65 /// # Parameters
66 ///
67 /// * `delay` - Minimum delay before the task becomes runnable.
68 /// * `task` - Callable to execute after the delay elapses.
69 ///
70 /// # Returns
71 ///
72 /// A tracked handle for observing or cancelling the scheduled task.
73 ///
74 /// # Errors
75 ///
76 /// Returns [`SubmissionError`] when the service refuses the task before
77 /// accepting it.
78 #[inline]
79 fn schedule_callable<C, R, E>(
80 &self,
81 delay: Duration,
82 task: C,
83 ) -> Result<Self::TrackedHandle<R, E>, SubmissionError>
84 where
85 C: Callable<R, E> + Send + 'static,
86 R: Send + 'static,
87 E: Send + 'static,
88 {
89 self.schedule_callable_at(Instant::now() + delay, task)
90 }
91
92 /// Schedules a runnable task to start at a monotonic instant.
93 ///
94 /// # Parameters
95 ///
96 /// * `instant` - Monotonic instant at which the task becomes runnable.
97 /// * `task` - Runnable to execute at or after the instant.
98 ///
99 /// # Returns
100 ///
101 /// A tracked handle for observing or cancelling the scheduled task.
102 ///
103 /// # Errors
104 ///
105 /// Returns [`SubmissionError`] when the service refuses the task before
106 /// accepting it.
107 #[inline]
108 fn schedule_at<T, E>(
109 &self,
110 instant: Instant,
111 task: T,
112 ) -> Result<Self::TrackedHandle<(), E>, SubmissionError>
113 where
114 T: Runnable<E> + Send + 'static,
115 E: Send + 'static,
116 {
117 let mut task = task;
118 self.schedule_callable_at(instant, move || task.run())
119 }
120
121 /// Schedules a callable task to start at a monotonic instant.
122 ///
123 /// # Parameters
124 ///
125 /// * `instant` - Monotonic instant at which the task becomes runnable.
126 /// * `task` - Callable to execute at or after the instant.
127 ///
128 /// # Returns
129 ///
130 /// A tracked handle for observing or cancelling the scheduled task.
131 ///
132 /// # Errors
133 ///
134 /// Returns [`SubmissionError`] when the service refuses the task before
135 /// accepting it.
136 fn schedule_callable_at<C, R, E>(
137 &self,
138 instant: Instant,
139 task: C,
140 ) -> Result<Self::TrackedHandle<R, E>, SubmissionError>
141 where
142 C: Callable<R, E> + Send + 'static,
143 R: Send + 'static,
144 E: Send + 'static;
145}