cala_server/job/
traits.rs1use async_trait::async_trait;
2use chrono::{DateTime, Utc};
3
4use super::{
5 current::CurrentJob,
6 entity::{Job, JobType},
7};
8use cala_ledger::CalaLedger;
9
10pub trait JobInitializer: Send + Sync + 'static {
11 fn job_type() -> JobType
12 where
13 Self: Sized;
14
15 fn retry_on_error_settings() -> RetrySettings
16 where
17 Self: Sized,
18 {
19 Default::default()
20 }
21
22 fn init(
23 &self,
24 job: Job,
25 ledger: &CalaLedger,
26 ) -> Result<Box<dyn JobRunner>, Box<dyn std::error::Error>>;
27}
28
29pub enum JobCompletion {
30 Complete,
31 CompleteWithTx(sqlx::Transaction<'static, sqlx::Postgres>),
32 RescheduleAt(DateTime<Utc>),
33 RescheduleAtWithTx(sqlx::Transaction<'static, sqlx::Postgres>, DateTime<Utc>),
34}
35
36#[async_trait]
37pub trait JobRunner: Send + Sync + 'static {
38 async fn run(
39 &self,
40 current_job: CurrentJob,
41 ) -> Result<JobCompletion, Box<dyn std::error::Error>>;
42}
43
44pub struct RetrySettings {
45 pub n_attempts: u32,
46 pub min_backoff: std::time::Duration,
47 pub max_backoff: std::time::Duration,
48}
49
50impl RetrySettings {
51 pub(super) fn next_attempt_at(&self, attempt: u32) -> DateTime<Utc> {
52 let backoff = std::cmp::min(
53 self.min_backoff.as_secs() * 2u64.pow(attempt - 1),
54 self.max_backoff.as_secs(),
55 );
56 chrono::Utc::now() + std::time::Duration::from_secs(backoff)
57 }
58}
59
60impl Default for RetrySettings {
61 fn default() -> Self {
62 Self {
63 n_attempts: 10,
64 min_backoff: std::time::Duration::from_secs(1),
65 max_backoff: std::time::Duration::from_secs(60),
66 }
67 }
68}