Skip to main content

reifydb_sub_task/
schedule.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::time::{Duration, Instant};
5
6/// Defines when and how often a task should be executed
7#[derive(Debug, Clone)]
8pub enum Schedule {
9	/// Execute at fixed intervals (interval starts after task completion)
10	FixedInterval(Duration),
11	/// Execute once after a delay
12	Once(Duration),
13}
14
15impl Schedule {
16	/// Calculate the next execution time after the given instant
17	/// Returns None for one-shot tasks
18	pub fn next_execution(&self, after: Instant) -> Option<Instant> {
19		match self {
20			Schedule::FixedInterval(duration) => Some(after + *duration),
21			Schedule::Once(_) => None,
22		}
23	}
24
25	/// Get the initial delay for first execution
26	pub fn initial_delay(&self) -> Duration {
27		match self {
28			Schedule::FixedInterval(duration) => *duration,
29			Schedule::Once(delay) => *delay,
30		}
31	}
32
33	/// Validate the schedule
34	pub fn validate(&self) -> Result<(), String> {
35		match self {
36			Schedule::FixedInterval(duration) => {
37				if duration.is_zero() {
38					return Err("FixedInterval duration cannot be zero".to_string());
39				}
40				Ok(())
41			}
42			Schedule::Once(delay) => {
43				if delay.is_zero() {
44					return Err("Once delay cannot be zero".to_string());
45				}
46				Ok(())
47			}
48		}
49	}
50}
51
52#[cfg(test)]
53mod tests {
54	use super::*;
55
56	#[test]
57	fn test_fixed_interval_next_execution() {
58		let schedule = Schedule::FixedInterval(Duration::from_secs(10));
59		let now = Instant::now();
60		let next = schedule.next_execution(now);
61		assert!(next.is_some());
62		assert_eq!(next.unwrap(), now + Duration::from_secs(10));
63	}
64
65	#[test]
66	fn test_once_next_execution() {
67		let schedule = Schedule::Once(Duration::from_secs(5));
68		let now = Instant::now();
69		let next = schedule.next_execution(now);
70		assert!(next.is_none());
71	}
72
73	#[test]
74	fn test_initial_delay() {
75		let interval = Schedule::FixedInterval(Duration::from_secs(30));
76		assert_eq!(interval.initial_delay(), Duration::from_secs(30));
77
78		let once = Schedule::Once(Duration::from_secs(5));
79		assert_eq!(once.initial_delay(), Duration::from_secs(5));
80	}
81
82	#[test]
83	fn test_validation() {
84		let valid = Schedule::FixedInterval(Duration::from_secs(1));
85		assert!(valid.validate().is_ok());
86
87		let invalid = Schedule::FixedInterval(Duration::ZERO);
88		assert!(invalid.validate().is_err());
89	}
90}