1use std::time::SystemTime;
4
5use ora_proto::{
6 common::v1::TimeRange,
7 server::v1::{self, JobExecutionStatus, JobQueryOrder},
8};
9use uuid::Uuid;
10
11use crate::{job_definition::JobStatus, IndexSet, JobType};
12
13#[derive(Debug, Clone, Default)]
15#[must_use]
16pub struct JobFilter {
17 pub job_ids: IndexSet<Uuid>,
21 pub job_type_ids: IndexSet<String>,
25 pub execution_ids: IndexSet<Uuid>,
29 pub schedule_ids: IndexSet<Uuid>,
31 pub status: IndexSet<JobStatus>,
40 pub labels: Vec<JobLabelFilter>,
45 pub active: Option<bool>,
49 pub created_after: Option<SystemTime>,
53 pub created_before: Option<SystemTime>,
57 pub target_execution_time_after: Option<SystemTime>,
61 pub target_execution_time_before: Option<SystemTime>,
65}
66
67impl JobFilter {
68 pub fn new() -> Self {
70 Self::default()
71 }
72
73 pub fn with_job_id(mut self, job_id: Uuid) -> Self {
75 self.job_ids.insert(job_id);
76 self
77 }
78
79 pub fn with_job_ids(mut self, job_ids: impl IntoIterator<Item = Uuid>) -> Self {
81 self.job_ids.extend(job_ids);
82 self
83 }
84
85 pub fn with_job_type_id(mut self, job_type_id: impl Into<String>) -> Self {
87 self.job_type_ids.insert(job_type_id.into());
88 self
89 }
90
91 pub fn with_job_type_ids(mut self, job_type_ids: impl IntoIterator<Item = String>) -> Self {
93 self.job_type_ids.extend(job_type_ids);
94 self
95 }
96
97 pub fn with_execution_id(mut self, execution_id: Uuid) -> Self {
99 self.execution_ids.insert(execution_id);
100 self
101 }
102
103 pub fn with_execution_ids(mut self, execution_ids: impl IntoIterator<Item = Uuid>) -> Self {
105 self.execution_ids.extend(execution_ids);
106 self
107 }
108
109 pub fn with_schedule_id(mut self, schedule_id: Uuid) -> Self {
111 self.schedule_ids.insert(schedule_id);
112 self
113 }
114
115 pub fn with_schedule_ids(mut self, schedule_ids: impl IntoIterator<Item = Uuid>) -> Self {
117 self.schedule_ids.extend(schedule_ids);
118 self
119 }
120
121 pub fn include_status(mut self, status: JobStatus) -> Self {
123 self.status.insert(status);
124 self
125 }
126
127 pub fn include_pending(mut self) -> Self {
129 self.status.insert(JobStatus::Pending);
130 self
131 }
132
133 pub fn include_ready(mut self) -> Self {
135 self.status.insert(JobStatus::Ready);
136 self
137 }
138
139 pub fn include_assigned(mut self) -> Self {
141 self.status.insert(JobStatus::Assigned);
142 self
143 }
144
145 pub fn include_running(mut self) -> Self {
147 self.status.insert(JobStatus::Running);
148 self
149 }
150
151 pub fn include_succeeded(mut self) -> Self {
153 self.status.insert(JobStatus::Succeeded);
154 self
155 }
156
157 pub fn include_failed(mut self) -> Self {
159 self.status.insert(JobStatus::Failed);
160 self
161 }
162
163 pub fn active_only(mut self) -> Self {
165 self.active = Some(true);
166 self
167 }
168
169 pub fn inactive_only(mut self) -> Self {
171 self.active = Some(false);
172 self
173 }
174
175 pub fn with_label_value(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
177 self.labels.push(JobLabelFilter {
178 key: key.into(),
179 value: JobLabelFilterValue::Equals(value.into()),
180 });
181 self
182 }
183
184 pub fn with_label(mut self, key: impl Into<String>) -> Self {
186 self.labels.push(JobLabelFilter {
187 key: key.into(),
188 value: JobLabelFilterValue::Exists,
189 });
190 self
191 }
192
193 pub fn include_job_type<J>(self) -> Self
195 where
196 J: JobType,
197 {
198 self.with_job_type_id(J::id())
199 }
200
201 pub fn created_after(mut self, time: SystemTime) -> Self {
205 self.created_after = Some(time);
206 self
207 }
208
209 pub fn created_before(mut self, time: SystemTime) -> Self {
213 self.created_before = Some(time);
214 self
215 }
216
217 pub fn target_execution_after(mut self, time: SystemTime) -> Self {
221 self.target_execution_time_after = Some(time);
222 self
223 }
224
225 pub fn target_execution_before(mut self, time: SystemTime) -> Self {
229 self.target_execution_time_before = Some(time);
230 self
231 }
232}
233
234impl From<JobFilter> for v1::JobQueryFilter {
235 fn from(filter: JobFilter) -> Self {
236 Self {
237 job_ids: filter
238 .job_ids
239 .into_iter()
240 .map(|id| id.to_string())
241 .collect(),
242 job_type_ids: filter
243 .job_type_ids
244 .into_iter()
245 .map(|id| id.to_string())
246 .collect(),
247 execution_ids: filter
248 .execution_ids
249 .into_iter()
250 .map(|id| id.to_string())
251 .collect(),
252 schedule_ids: filter
253 .schedule_ids
254 .into_iter()
255 .map(|id| id.to_string())
256 .collect(),
257 status: filter
258 .status
259 .into_iter()
260 .map(|s| JobExecutionStatus::from(s).into())
261 .collect(),
262 labels: filter.labels.into_iter().map(Into::into).collect(),
263 active: filter.active,
264 created_at: Some(TimeRange {
265 start: filter.created_after.map(Into::into),
266 end: filter.created_before.map(Into::into),
267 }),
268 target_execution_time: Some(TimeRange {
269 start: filter.target_execution_time_after.map(Into::into),
270 end: filter.target_execution_time_before.map(Into::into),
271 }),
272 }
273 }
274}
275
276#[derive(Debug, Clone)]
278pub struct JobLabelFilter {
279 pub key: String,
281 pub value: JobLabelFilterValue,
283}
284
285#[derive(Debug, Clone)]
287pub enum JobLabelFilterValue {
288 Exists,
290 Equals(String),
292}
293
294impl From<JobLabelFilter> for v1::JobLabelFilter {
295 fn from(filter: JobLabelFilter) -> Self {
296 Self {
297 key: filter.key,
298 value: match filter.value {
299 JobLabelFilterValue::Exists => Some(v1::job_label_filter::Value::Exists(
300 v1::LabelFilterExistCondition::Exists.into(),
301 )),
302 JobLabelFilterValue::Equals(value) => {
303 Some(v1::job_label_filter::Value::Equals(value))
304 }
305 },
306 }
307 }
308}
309
310#[derive(Debug, Default, Clone, Copy)]
312pub enum JobOrder {
313 CreatedAtAsc,
315 #[default]
317 CreatedAtDesc,
318 TargetExecutionTimeAsc,
320 TargetExecutionTimeDesc,
322}
323
324impl From<JobOrder> for JobQueryOrder {
325 fn from(value: JobOrder) -> Self {
326 match value {
327 JobOrder::CreatedAtAsc => Self::CreatedAtAsc,
328 JobOrder::CreatedAtDesc => Self::CreatedAtDesc,
329 JobOrder::TargetExecutionTimeAsc => Self::TargetExecutionTimeAsc,
330 JobOrder::TargetExecutionTimeDesc => Self::TargetExecutionTimeDesc,
331 }
332 }
333}