ora_client/schedule_definition.rs
1//! Schedule definitions and details.
2
3use std::time::{Duration, SystemTime};
4
5use serde::Serialize;
6use uuid::Uuid;
7
8use crate::{IndexMap, JobDefinition};
9
10/// A new schedule.
11#[derive(Debug, Clone)]
12#[must_use]
13pub struct ScheduleDefinition {
14 /// Scheduling policy for the schedule.
15 pub job_timing_policy: ScheduleJobTimingPolicy,
16 /// Policy for new jobs created by the schedule.
17 pub job_creation_policy: ScheduleJobCreationPolicy,
18 /// Labels of the schedule.
19 pub labels: IndexMap<String, String>,
20 /// The time range for the schedule.
21 ///
22 /// The schedule must not start before `start` and must end before `end`.
23 pub time_range: Option<ScheduleTimeRange>,
24 /// Arbitrary metadata in JSON format.
25 pub metadata_json: Option<String>,
26 /// Whether to copy schedule labels to created jobs.
27 ///
28 /// Labels are not overwritten if they already exist on the job.
29 ///
30 /// Note that this is a client-side operation
31 /// that is done before the schedule is submitted to the server
32 /// for creation.
33 ///
34 /// By default, this is `true`.
35 pub propagate_labels_to_jobs: bool,
36}
37
38impl ScheduleDefinition {
39 /// Set the schedule to immediately create a job when started.
40 ///
41 /// This is a no-op for timing policies that do not support it.
42 pub fn immediate(mut self) -> Self {
43 match &mut self.job_timing_policy {
44 ScheduleJobTimingPolicy::Repeat(policy) => policy.immediate = true,
45 ScheduleJobTimingPolicy::Cron(policy) => policy.immediate = true,
46 }
47 self
48 }
49
50 /// Set a start time for the schedule.
51 pub fn start_after(mut self, start: SystemTime) -> Self {
52 if let Some(time_range) = self.time_range.as_mut() {
53 time_range.start = Some(start);
54 } else {
55 self.time_range = Some(ScheduleTimeRange {
56 start: Some(start),
57 end: None,
58 });
59 }
60 self
61 }
62
63 /// Set an end time for the schedule.
64 pub fn end_before(mut self, end: SystemTime) -> Self {
65 if let Some(time_range) = self.time_range.as_mut() {
66 time_range.end = Some(end);
67 } else {
68 self.time_range = Some(ScheduleTimeRange {
69 start: None,
70 end: Some(end),
71 });
72 }
73 self
74 }
75
76 /// Add a label to the schedule.
77 ///
78 /// Note that this will not set any labels
79 /// for jobs created by the schedule.
80 pub fn with_label(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
81 self.labels.insert(key.into(), value.into());
82 self
83 }
84
85 /// Add a JSON label to the schedule.
86 ///
87 /// # Panics
88 ///
89 /// If the value cannot be serialized to JSON.
90 pub fn with_label_json(mut self, key: impl Into<String>, value: impl Serialize) -> Self {
91 self.labels.insert(
92 key.into(),
93 serde_json::to_string(&value).expect("label serialization failed"),
94 );
95 self
96 }
97
98 /// Set additional metadata for the schedule.
99 ///
100 /// Note that this will replace any existing metadata.
101 ///
102 /// # Panics
103 ///
104 /// If the metadata cannot be serialized to JSON.
105 pub fn replace_metadata(mut self, metadata: impl Serialize) -> Self {
106 self.metadata_json =
107 Some(serde_json::to_string(&metadata).expect("metadata serialization failed"));
108 self
109 }
110
111 /// Whether to propagate schedule labels to created jobs.
112 ///
113 /// Labels are not overwritten if they already exist on the job.
114 ///
115 /// Note that this is a client-side operation
116 /// that is done before the schedule is submitted to the server
117 /// for creation.
118 ///
119 /// By default, this is `true`.
120 pub fn propagate_labels(mut self, propagate: bool) -> Self {
121 self.propagate_labels_to_jobs = propagate;
122 self
123 }
124}
125
126/// Scheduling policy for a schedule.
127#[derive(Debug, Clone)]
128pub enum ScheduleJobTimingPolicy {
129 /// A schedule that repeats.
130 Repeat(ScheduleJobTimingPolicyRepeat),
131 /// A schedule based on a cron expression.
132 Cron(ScheduleJobTimingPolicyCron),
133}
134
135/// Scheduling policy for a schedule that repeats.
136#[derive(Debug, Clone)]
137pub struct ScheduleJobTimingPolicyRepeat {
138 /// The interval between each job.
139 pub interval: Duration,
140 /// Whether the schedule should create a job immediately.
141 pub immediate: bool,
142 /// The policy for missed jobs.
143 pub missed_time_policy: ScheduleMissedTimePolicy,
144}
145
146/// Scheduling policy based on a cron expression.
147#[derive(Debug, Clone)]
148pub struct ScheduleJobTimingPolicyCron {
149 /// The cron expression.
150 pub cron_expression: String,
151 /// Whether the schedule should create a job immediately.
152 pub immediate: bool,
153 /// The policy for missed jobs.
154 pub missed_time_policy: ScheduleMissedTimePolicy,
155}
156
157/// Policy for missed jobs.
158#[derive(Debug, Default, Clone, Copy)]
159pub enum ScheduleMissedTimePolicy {
160 /// Skip any missed times.
161 #[default]
162 Skip,
163 /// Create a job for each missed time.
164 Create,
165}
166
167/// Policy for new jobs created by a schedule.
168#[derive(Debug, Clone)]
169pub enum ScheduleJobCreationPolicy {
170 /// Create a new job from the given job definition.
171 JobDefinition(JobDefinition),
172}
173
174/// The time range for a schedule.
175#[derive(Debug, Clone, Copy)]
176pub struct ScheduleTimeRange {
177 /// The schedule must not start before this time.
178 pub start: Option<SystemTime>,
179 /// The schedule must end before this time.
180 pub end: Option<SystemTime>,
181}
182
183/// Details of a schedule.
184///
185/// Associated jobs are not included on purpose
186/// as there can be many jobs associated with a schedule,
187/// additional queries can be made to get the jobs.
188#[derive(Debug, Clone)]
189pub struct ScheduleDetails {
190 /// The unique identifier of the schedule.
191 pub id: Uuid,
192 /// The time the schedule was created.
193 pub created_at: SystemTime,
194 /// Scheduling policy for the schedule.
195 pub job_timing_policy: ScheduleJobTimingPolicy,
196 /// Policy for new jobs created by the schedule.
197 pub job_creation_policy: ScheduleJobCreationPolicy,
198 /// Labels of the schedule.
199 pub labels: IndexMap<String, String>,
200 /// Whether the schedule is active.
201 pub active: bool,
202 /// Whether the schedule was cancelled.
203 pub cancelled: bool,
204 /// The time range for the schedule.
205 pub time_range: Option<ScheduleTimeRange>,
206 /// Arbitrary metadata in JSON format.
207 pub metadata_json: Option<String>,
208}