1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use sqlx::prelude::FromRow;
4use std::fmt;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
8#[sqlx(type_name = "awa.job_state", rename_all = "snake_case")]
9#[serde(rename_all = "snake_case")]
10pub enum JobState {
11 Scheduled,
12 Available,
13 Running,
14 Completed,
15 Retryable,
16 Failed,
17 Cancelled,
18}
19
20impl fmt::Display for JobState {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 JobState::Scheduled => write!(f, "scheduled"),
24 JobState::Available => write!(f, "available"),
25 JobState::Running => write!(f, "running"),
26 JobState::Completed => write!(f, "completed"),
27 JobState::Retryable => write!(f, "retryable"),
28 JobState::Failed => write!(f, "failed"),
29 JobState::Cancelled => write!(f, "cancelled"),
30 }
31 }
32}
33
34impl JobState {
35 pub fn bit_position(&self) -> u8 {
37 match self {
38 JobState::Scheduled => 0,
39 JobState::Available => 1,
40 JobState::Running => 2,
41 JobState::Completed => 3,
42 JobState::Retryable => 4,
43 JobState::Failed => 5,
44 JobState::Cancelled => 6,
45 }
46 }
47
48 pub fn is_terminal(&self) -> bool {
50 matches!(
51 self,
52 JobState::Completed | JobState::Failed | JobState::Cancelled
53 )
54 }
55}
56
57#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
59pub struct JobRow {
60 pub id: i64,
61 pub kind: String,
62 pub queue: String,
63 pub args: serde_json::Value,
64 pub state: JobState,
65 pub priority: i16,
66 pub attempt: i16,
67 pub max_attempts: i16,
68 pub run_at: DateTime<Utc>,
69 pub heartbeat_at: Option<DateTime<Utc>>,
70 pub deadline_at: Option<DateTime<Utc>>,
71 pub attempted_at: Option<DateTime<Utc>>,
72 pub finalized_at: Option<DateTime<Utc>>,
73 pub created_at: DateTime<Utc>,
74 pub errors: Option<Vec<serde_json::Value>>,
75 pub metadata: serde_json::Value,
76 pub tags: Vec<String>,
77 pub unique_key: Option<Vec<u8>>,
78 #[sqlx(skip)]
81 pub unique_states: Option<u8>,
82}
83
84#[derive(Debug, Clone)]
86pub struct InsertOpts {
87 pub queue: String,
88 pub priority: i16,
89 pub max_attempts: i16,
90 pub run_at: Option<DateTime<Utc>>,
91 pub deadline_duration: Option<chrono::Duration>,
92 pub metadata: serde_json::Value,
93 pub tags: Vec<String>,
94 pub unique: Option<UniqueOpts>,
95}
96
97impl Default for InsertOpts {
98 fn default() -> Self {
99 Self {
100 queue: "default".to_string(),
101 priority: 2,
102 max_attempts: 25,
103 run_at: None,
104 deadline_duration: None,
105 metadata: serde_json::json!({}),
106 tags: Vec::new(),
107 unique: None,
108 }
109 }
110}
111
112#[derive(Debug, Clone)]
114pub struct UniqueOpts {
115 pub by_queue: bool,
117 pub by_args: bool,
119 pub by_period: Option<i64>,
121 pub states: u8,
124}
125
126impl Default for UniqueOpts {
127 fn default() -> Self {
128 Self {
129 by_queue: false,
130 by_args: true,
131 by_period: None,
132 states: 0b0001_1111,
134 }
135 }
136}
137
138impl UniqueOpts {
139 pub fn states_bits(&self) -> Vec<u8> {
141 vec![self.states]
142 }
143}
144
145#[derive(Debug, Clone)]
147pub struct InsertParams {
148 pub kind: String,
149 pub args: serde_json::Value,
150 pub opts: InsertOpts,
151}