1use super::types::{
2 page_repeat_entries, Job, JobEvent, JobFinishedResult, JobFlow, JobFlowChildValues,
3 JobFlowDependencies, JobFlowDependencyCountOptions, JobFlowDependencyCounts,
4 JobFlowDependencyPage, JobFlowDependencyPageOptions, JobFlowDependencyPages,
5 JobFlowDependencyPagesOptions, JobFlowDependencySelectedCounts, JobFlowDependencyValues,
6 JobFlowIgnoredFailures, JobId, JobLeaseRenewal, JobListOptions, JobListPage, JobLogPage,
7 JobOptions, JobPriority, JobPriorityCount, JobQueueStats, JobRepeatEntry, JobRepeatListOptions,
8 JobRepeatPage, JobSpec, JobState, JobStateCount, JobWorkerId,
9};
10use crate::error::Result;
11use async_trait::async_trait;
12use chrono::{DateTime, Utc};
13use serde_json::Value;
14use std::time::Duration;
15
16#[async_trait]
18pub trait JobQueueBackend: Send + Sync {
19 async fn add_job(&self, name: String, payload: Value, options: JobOptions) -> Result<Job>;
20
21 async fn add_jobs(&self, jobs: Vec<JobSpec>, now: DateTime<Utc>) -> Result<Vec<Job>>;
23
24 async fn add_flow(
25 &self,
26 parent: JobSpec,
27 children: Vec<JobSpec>,
28 now: DateTime<Utc>,
29 ) -> Result<JobFlow>;
30
31 async fn add_flow_children(
38 &self,
39 parent_id: &str,
40 lock_token: &str,
41 children: Vec<JobSpec>,
42 now: DateTime<Utc>,
43 ) -> Result<Vec<Job>>;
44
45 async fn get_flow_dependencies(&self, parent_id: &str) -> Result<Option<JobFlowDependencies>>;
46
47 async fn get_flow_dependency_counts(
48 &self,
49 parent_id: &str,
50 ) -> Result<Option<JobFlowDependencyCounts>>;
51
52 async fn get_flow_dependency_selected_counts(
54 &self,
55 parent_id: &str,
56 options: JobFlowDependencyCountOptions,
57 ) -> Result<Option<JobFlowDependencySelectedCounts>>;
58
59 async fn get_flow_dependency_values(
61 &self,
62 parent_id: &str,
63 ) -> Result<Option<JobFlowDependencyValues>>;
64
65 async fn get_flow_dependency_page(
67 &self,
68 parent_id: &str,
69 options: JobFlowDependencyPageOptions,
70 ) -> Result<Option<JobFlowDependencyPage>>;
71
72 async fn get_flow_dependency_pages(
74 &self,
75 parent_id: &str,
76 options: JobFlowDependencyPagesOptions,
77 ) -> Result<Option<JobFlowDependencyPages>>;
78
79 async fn get_flow_children_values(&self, parent_id: &str)
84 -> Result<Option<JobFlowChildValues>>;
85
86 async fn get_flow_ignored_children_failures(
91 &self,
92 parent_id: &str,
93 ) -> Result<Option<JobFlowIgnoredFailures>>;
94
95 async fn remove_unprocessed_children(
96 &self,
97 parent_id: &str,
98 now: DateTime<Utc>,
99 ) -> Result<Option<Vec<Job>>>;
100
101 async fn remove_child_dependency(&self, child_id: &str, now: DateTime<Utc>) -> Result<bool>;
102
103 async fn claim_next(
104 &self,
105 worker_id: JobWorkerId,
106 lease_for: Duration,
107 now: DateTime<Utc>,
108 ) -> Result<Option<Job>>;
109
110 async fn claim_next_blocking(
117 &self,
118 worker_id: JobWorkerId,
119 lease_for: Duration,
120 _block_for: Duration,
121 ) -> Result<Option<Job>> {
122 self.claim_next(worker_id, lease_for, Utc::now()).await
123 }
124
125 async fn complete_job(
126 &self,
127 job_id: &str,
128 lock_token: &str,
129 value: Value,
130 now: DateTime<Utc>,
131 ) -> Result<Job>;
132
133 async fn fail_job(
134 &self,
135 job_id: &str,
136 lock_token: &str,
137 error: String,
138 now: DateTime<Utc>,
139 ) -> Result<Job>;
140
141 async fn fail_job_discarding_retry(
147 &self,
148 job_id: &str,
149 lock_token: &str,
150 error: String,
151 now: DateTime<Utc>,
152 ) -> Result<Job>;
153
154 async fn renew_lease(
155 &self,
156 job_id: &str,
157 lock_token: &str,
158 lease_for: Duration,
159 now: DateTime<Utc>,
160 ) -> Result<Job>;
161
162 async fn renew_leases(
169 &self,
170 renewals: &[JobLeaseRenewal],
171 lease_for: Duration,
172 now: DateTime<Utc>,
173 ) -> Result<Vec<JobId>> {
174 let mut failed = Vec::new();
175 for renewal in renewals {
176 if self
177 .renew_lease(&renewal.job_id, &renewal.lock_token, lease_for, now)
178 .await
179 .is_err()
180 {
181 failed.push(renewal.job_id.clone());
182 }
183 }
184 Ok(failed)
185 }
186
187 async fn delay_active_job(
188 &self,
189 job_id: &str,
190 lock_token: &str,
191 delay: Duration,
192 now: DateTime<Utc>,
193 ) -> Result<Job>;
194
195 async fn release_active_job(
196 &self,
197 job_id: &str,
198 lock_token: &str,
199 now: DateTime<Utc>,
200 ) -> Result<Job>;
201
202 async fn promote_job(&self, job_id: &str, now: DateTime<Utc>) -> Result<Job>;
203
204 async fn reschedule_job(
205 &self,
206 job_id: &str,
207 delay: Duration,
208 now: DateTime<Utc>,
209 ) -> Result<Job>;
210
211 async fn retry_job(&self, job_id: &str, now: DateTime<Utc>) -> Result<Job>;
213
214 async fn update_priority(&self, job_id: &str, priority: JobPriority) -> Result<Job>;
220
221 async fn update_priority_with_lifo(
227 &self,
228 job_id: &str,
229 priority: JobPriority,
230 _lifo: bool,
231 ) -> Result<Job> {
232 self.update_priority(job_id, priority).await
233 }
234
235 async fn remove_job(&self, job_id: &str) -> Result<Option<Job>>;
236
237 async fn remove_repeat(&self, repeat_key: &str) -> Result<Option<Job>>;
238
239 async fn remove_deduplication_key(&self, deduplication_id: &str) -> Result<bool>;
240
241 async fn get_deduplication_job_id(&self, deduplication_id: &str) -> Result<Option<JobId>>;
242
243 async fn list_repeats(&self) -> Result<Vec<JobRepeatEntry>>;
244
245 async fn upsert_repeat(&self, spec: JobSpec, now: DateTime<Utc>) -> Result<Job>;
253
254 async fn get_repeat(&self, repeat_key: &str) -> Result<Option<JobRepeatEntry>> {
256 Ok(self
257 .list_repeats()
258 .await?
259 .into_iter()
260 .find(|entry| entry.key == repeat_key))
261 }
262
263 async fn count_repeats(&self) -> Result<usize> {
265 Ok(self.list_repeats().await?.len())
266 }
267
268 async fn list_repeats_page(&self, options: JobRepeatListOptions) -> Result<JobRepeatPage> {
273 Ok(page_repeat_entries(self.list_repeats().await?, options))
274 }
275
276 async fn clean_jobs(
277 &self,
278 state: JobState,
279 grace: Duration,
280 limit: usize,
281 now: DateTime<Utc>,
282 ) -> Result<Vec<Job>>;
283
284 async fn drain_jobs(&self, include_delayed: bool) -> Result<Vec<Job>>;
285
286 async fn obliterate(&self, force: bool) -> Result<usize>;
292
293 async fn list_jobs(&self, options: JobListOptions) -> Result<JobListPage>;
294
295 async fn get_job_counts(&self, states: &[JobState]) -> Result<Vec<JobStateCount>>;
300
301 async fn get_job_count(&self, states: &[JobState]) -> Result<usize> {
307 let counts = self.get_job_counts(states).await?;
308 Ok(counts.into_iter().map(|count| count.count).sum())
309 }
310
311 async fn count_pending_jobs(&self) -> Result<usize> {
316 self.get_job_count(JobState::PENDING.as_slice()).await
317 }
318
319 async fn get_counts_per_priority(
323 &self,
324 priorities: &[JobPriority],
325 ) -> Result<Vec<JobPriorityCount>>;
326
327 async fn update_data(&self, job_id: &str, payload: Value) -> Result<Job>;
328
329 async fn update_progress(&self, job_id: &str, progress: Value) -> Result<Job>;
335
336 async fn save_stacktrace(
342 &self,
343 job_id: &str,
344 stacktrace: Vec<String>,
345 failed_reason: String,
346 ) -> Result<Job>;
347
348 async fn add_log(
349 &self,
350 job_id: &str,
351 line: String,
352 keep: usize,
353 now: DateTime<Utc>,
354 ) -> Result<Job>;
355
356 async fn get_job_logs(
357 &self,
358 job_id: &str,
359 start: isize,
360 end: isize,
361 ascending: bool,
362 ) -> Result<JobLogPage>;
363
364 async fn clear_job_logs(&self, job_id: &str, keep: usize) -> Result<JobLogPage>;
370
371 async fn read_events(&self, _start: &str, _end: &str, _limit: usize) -> Result<Vec<JobEvent>> {
377 Ok(Vec::new())
378 }
379
380 async fn trim_events(&self, _max_len: usize) -> Result<usize> {
382 Ok(0)
383 }
384
385 async fn promote_due_jobs(&self, now: DateTime<Utc>) -> Result<usize>;
386
387 async fn recover_stalled_jobs(&self, now: DateTime<Utc>) -> Result<usize>;
388
389 async fn pause(&self) -> Result<()>;
390
391 async fn resume(&self) -> Result<()>;
392
393 async fn is_paused(&self) -> Result<bool>;
395
396 async fn get_job(&self, job_id: &str) -> Result<Option<Job>>;
397
398 async fn get_job_state(&self, job_id: &str) -> Result<Option<JobState>>;
399
400 async fn get_job_finished_result(&self, job_id: &str) -> Result<Option<JobFinishedResult>>;
407
408 async fn stats(&self) -> Result<JobQueueStats>;
409}