sdf_metadata/metadata/dataflow/
schedule_config.rs

1use croner::Cron;
2
3use crate::{
4    util::config_error::{ConfigError, INDENT},
5    wit::dataflow::{ScheduleConfig, Schedule as ScheduleWit},
6};
7
8impl ScheduleConfig {
9    pub fn validate(&self) -> Result<(), ScheduleValidationFailure> {
10        match &self.schedule {
11            ScheduleWit::Cron(format) => match Cron::new(format).parse() {
12                Ok(_) => Ok(()),
13                Err(e) => Err(ScheduleValidationFailure {
14                    name: self.name.clone(),
15                    errors: vec![ScheduleValidationError::InvalidSchedule(e.to_string())],
16                }),
17            },
18        }
19    }
20
21    pub fn as_cron(&self) -> Option<Cron> {
22        match &self.schedule {
23            ScheduleWit::Cron(format) => Cron::new(format).parse().ok(),
24        }
25    }
26}
27
28#[derive(Debug, Clone, Eq, PartialEq)]
29pub struct ScheduleValidationFailure {
30    pub name: String,
31    pub errors: Vec<ScheduleValidationError>,
32}
33
34#[derive(Debug, Clone, Eq, PartialEq)]
35pub enum ScheduleValidationError {
36    InvalidSchedule(String),
37}
38
39impl ConfigError for ScheduleValidationFailure {
40    fn readable(&self, indents: usize) -> String {
41        let mut result = format!(
42            "{}Schedule `{}` is invalid:\n",
43            INDENT.repeat(indents),
44            self.name
45        );
46
47        for error in &self.errors {
48            result.push_str(&error.readable(indents + 1));
49        }
50
51        result
52    }
53}
54
55impl ConfigError for ScheduleValidationError {
56    fn readable(&self, indents: usize) -> String {
57        let indent = INDENT.repeat(indents);
58
59        match self {
60            Self::InvalidSchedule(error) => {
61                format!("{}Failed to parse cron config: {}\n", indent, error)
62            }
63        }
64    }
65}
66
67#[cfg(test)]
68mod test {
69    use super::*;
70
71    #[test]
72    fn test_validate_invalid_cron_format() {
73        let schedule = ScheduleConfig {
74            name: "test".to_string(),
75            schedule: ScheduleWit::Cron("invalid".to_string()),
76        };
77
78        let result = schedule.validate();
79        assert!(result.is_err());
80        let err = result.unwrap_err();
81        assert_eq!(err.name, "test");
82        assert_eq!(err.errors.len(), 1);
83        assert_eq!(
84            err.errors[0],
85            ScheduleValidationError::InvalidSchedule("Invalid pattern: Pattern must consist of five or six fields (minute, hour, day, month, day of week, and optional second).".to_string())
86        );
87    }
88}