1use super::{CronSchedule, JobTimeWindow};
2use chrono::{DateTime, Utc};
3use chrono_tz::{Asia::Shanghai, Tz};
4use std::time::Duration;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct StaggeredIntervalSchedule {
9 pub every: Duration,
10 pub seed: Option<String>,
11}
12
13impl StaggeredIntervalSchedule {
14 pub fn new(every: Duration) -> Self {
15 Self { every, seed: None }
16 }
17
18 pub fn with_seed(mut self, seed: impl Into<String>) -> Self {
19 self.seed = Some(seed.into());
20 self
21 }
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct GroupedIntervalSchedule {
27 pub every: Duration,
28 pub group_size: u32,
29 pub member_index: u32,
30 pub group_seed: Option<String>,
31}
32
33impl GroupedIntervalSchedule {
34 pub fn new(every: Duration, group_size: u32, member_index: u32) -> Self {
35 Self {
36 every,
37 group_size,
38 member_index,
39 group_seed: None,
40 }
41 }
42
43 pub fn with_group_seed(mut self, group_seed: impl Into<String>) -> Self {
44 self.group_seed = Some(group_seed.into());
45 self
46 }
47}
48
49#[derive(Debug, Clone, PartialEq, Eq)]
51pub struct GroupedCronSchedule {
52 pub cron: CronSchedule,
53 pub spread: Duration,
54 pub group_size: u32,
55 pub member_index: u32,
56 pub group_seed: Option<String>,
57}
58
59impl GroupedCronSchedule {
60 pub fn new(
61 cron: CronSchedule,
62 spread: Duration,
63 group_size: u32,
64 member_index: u32,
65 ) -> Self {
66 Self {
67 cron,
68 spread,
69 group_size,
70 member_index,
71 group_seed: None,
72 }
73 }
74
75 pub fn with_group_seed(mut self, group_seed: impl Into<String>) -> Self {
76 self.group_seed = Some(group_seed.into());
77 self
78 }
79}
80
81#[derive(Debug, Clone, PartialEq, Eq)]
83pub struct IntervalWindow {
84 pub window: JobTimeWindow,
85 pub every: Option<Duration>,
86}
87
88impl IntervalWindow {
89 pub fn new(window: JobTimeWindow, every: Option<Duration>) -> Self {
90 Self { window, every }
91 }
92}
93
94#[derive(Debug, Clone, PartialEq, Eq)]
99pub struct WindowedIntervalSchedule {
100 pub default_every: Option<Duration>,
101 pub windows: Vec<IntervalWindow>,
102}
103
104impl WindowedIntervalSchedule {
105 pub fn new(default_every: Option<Duration>) -> Self {
106 Self {
107 default_every,
108 windows: Vec::new(),
109 }
110 }
111
112 pub fn with_window(mut self, window: JobTimeWindow, every: Option<Duration>) -> Self {
113 self.windows.push(IntervalWindow::new(window, every));
114 self
115 }
116}
117
118#[derive(Debug, Clone, PartialEq, Eq)]
119pub enum Schedule {
120 Interval(Duration),
122 StaggeredInterval(StaggeredIntervalSchedule),
127 GroupedInterval(GroupedIntervalSchedule),
134 GroupedCron(GroupedCronSchedule),
141 WindowedInterval(WindowedIntervalSchedule),
143 AtTimes(Vec<DateTime<Tz>>),
148 Cron(CronSchedule),
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
156pub enum MissedRunPolicy {
157 Skip,
158 #[default]
159 CatchUpOnce,
160 ReplayAll,
161}
162
163#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
164pub enum OverlapPolicy {
165 #[default]
166 Forbid,
167 QueueOne,
168 AllowParallel,
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
172pub enum TimeWindowAlignment {
173 #[default]
174 Disabled,
175 AlignToNextWindow,
176}
177
178#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
179pub enum TerminalStatePolicy {
180 #[default]
181 Retain,
182 Delete,
183}
184
185#[derive(Debug, Clone)]
186pub struct SchedulerConfig {
187 pub timezone: Tz,
193 pub history_limit: usize,
195 pub terminal_state_policy: TerminalStatePolicy,
198}
199
200impl Default for SchedulerConfig {
201 fn default() -> Self {
202 Self {
203 timezone: Shanghai,
204 history_limit: 32,
205 terminal_state_policy: TerminalStatePolicy::Retain,
206 }
207 }
208}
209
210impl Schedule {
211 pub fn staggered_interval(every: Duration) -> Self {
214 Self::StaggeredInterval(StaggeredIntervalSchedule::new(every))
215 }
216
217 pub fn staggered_interval_with_seed(every: Duration, seed: impl Into<String>) -> Self {
219 Self::StaggeredInterval(StaggeredIntervalSchedule::new(every).with_seed(seed))
220 }
221
222 pub fn grouped_interval(every: Duration, group_size: u32, member_index: u32) -> Self {
224 Self::GroupedInterval(GroupedIntervalSchedule::new(
225 every,
226 group_size,
227 member_index,
228 ))
229 }
230
231 pub fn grouped_interval_with_seed(
234 every: Duration,
235 group_size: u32,
236 member_index: u32,
237 group_seed: impl Into<String>,
238 ) -> Self {
239 Self::GroupedInterval(
240 GroupedIntervalSchedule::new(every, group_size, member_index)
241 .with_group_seed(group_seed),
242 )
243 }
244
245 pub fn grouped_cron(
247 cron: CronSchedule,
248 spread: Duration,
249 group_size: u32,
250 member_index: u32,
251 ) -> Self {
252 Self::GroupedCron(GroupedCronSchedule::new(
253 cron,
254 spread,
255 group_size,
256 member_index,
257 ))
258 }
259
260 pub fn grouped_cron_with_seed(
263 cron: CronSchedule,
264 spread: Duration,
265 group_size: u32,
266 member_index: u32,
267 group_seed: impl Into<String>,
268 ) -> Self {
269 Self::GroupedCron(
270 GroupedCronSchedule::new(cron, spread, group_size, member_index)
271 .with_group_seed(group_seed),
272 )
273 }
274
275 pub fn windowed_interval(default_every: Option<Duration>) -> Self {
277 Self::WindowedInterval(WindowedIntervalSchedule::new(default_every))
278 }
279}
280
281pub(crate) fn utc_time(value: DateTime<Tz>) -> DateTime<Utc> {
282 value.with_timezone(&Utc)
283}