1use chrono::{DateTime, Utc};
2use runledger_core::jobs::{
3 JobEventType, JobFailure, JobFailureKind, JobStage, JobStatus, JobType, JobTypeName,
4};
5use serde_json::Value;
6use sqlx::types::Uuid;
7
8pub const JOB_SCHEDULE_MAX_JITTER_SECONDS: i32 = 86_400;
13
14pub const JOB_LIST_PAGE_LIMIT_MAX: i64 = 1_000;
19
20#[derive(Debug, Clone)]
21pub struct JobDefinitionUpsert<'a> {
22 pub job_type: JobType<'a>,
23 pub version: i32,
24 pub max_attempts: i32,
25 pub default_timeout_seconds: i32,
26 pub default_priority: i32,
27 pub is_enabled: bool,
28}
29
30#[derive(Debug, Clone)]
31pub struct JobDefinitionRecord {
32 pub job_type: JobTypeName,
33 pub version: i32,
34 pub max_attempts: i32,
35 pub default_timeout_seconds: i32,
36 pub default_priority: i32,
37 pub is_enabled: bool,
38 pub created_at: DateTime<Utc>,
39 pub updated_at: DateTime<Utc>,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
44pub struct JobScheduleJobTypeReference {
45 pub schedule_name: String,
47 pub job_type: JobTypeName,
49}
50
51#[derive(Debug, Clone)]
52pub struct JobDefinitionListFilter<'a> {
53 pub job_type: Option<&'a str>,
56 pub limit: i64,
57 pub offset: i64,
58}
59
60#[derive(Debug, Clone)]
61pub struct JobDefinitionUpdate {
62 pub max_attempts: Option<i32>,
63 pub default_timeout_seconds: Option<i32>,
64 pub default_priority: Option<i32>,
65 pub is_enabled: Option<bool>,
66}
67
68#[derive(Debug, Clone)]
69pub struct JobRuntimeConfigUpsert<'a> {
70 pub job_type: JobType<'a>,
71 pub schema_version: i32,
72 pub config: &'a Value,
73 pub updated_by_user_id: Option<Uuid>,
74}
75
76#[derive(Debug, Clone)]
77pub struct JobRuntimeConfigRecord {
78 pub job_type: JobTypeName,
79 pub schema_version: i32,
80 pub config: Value,
81 pub updated_by_user_id: Option<Uuid>,
82 pub created_at: DateTime<Utc>,
83 pub updated_at: DateTime<Utc>,
84}
85
86#[derive(Debug, Clone)]
87pub struct JobEnqueue<'a> {
88 pub job_type: JobType<'a>,
89 pub organization_id: Option<Uuid>,
90 pub payload: &'a Value,
91 pub priority: Option<i32>,
92 pub max_attempts: Option<i32>,
93 pub timeout_seconds: Option<i32>,
94 pub next_run_at: Option<DateTime<Utc>>,
98 pub idempotency_key: Option<&'a str>,
99 pub stage: Option<JobStage>,
100}
101
102#[derive(Debug, Clone)]
103pub struct JobScheduleRecord {
104 pub id: Uuid,
106 pub name: String,
108 pub job_type: JobTypeName,
110 pub organization_id: Option<Uuid>,
112 pub payload_template: Value,
115 pub cron_expr: String,
117 pub is_active: bool,
122 pub max_jitter_seconds: i32,
125 pub next_fire_at: DateTime<Utc>,
127}
128
129#[derive(Debug, Clone)]
148pub struct JobScheduleUpsert<'a> {
149 pub name: &'a str,
151 pub job_type: JobType<'a>,
153 pub organization_id: Option<Uuid>,
155 pub payload_template: &'a Value,
157 pub cron_expr: &'a str,
160 pub is_active: bool,
162 pub next_fire_at: DateTime<Utc>,
164 pub max_jitter_seconds: i32,
167}
168
169#[derive(Debug, Clone)]
171pub struct JobScheduleCatalogSyncEntry<'a> {
172 pub upsert: JobScheduleUpsert<'a>,
176}
177
178#[non_exhaustive]
180#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct JobScheduleCatalogSyncReport {
182 pub synced_schedule_names: Vec<String>,
184}
185
186#[derive(Debug, Clone)]
187pub struct JobQueueRecord {
188 pub id: Uuid,
189 pub job_type: JobTypeName,
190 pub organization_id: Option<Uuid>,
191 pub payload: Value,
192 pub status: JobStatus,
193 pub priority: i32,
194 pub run_number: i32,
195 pub attempt: i32,
196 pub max_attempts: i32,
197 pub timeout_seconds: i32,
198 pub next_run_at: DateTime<Utc>,
199 pub lease_expires_at: Option<DateTime<Utc>>,
200 pub last_heartbeat_at: Option<DateTime<Utc>>,
201 pub worker_id: Option<String>,
202 pub started_at: Option<DateTime<Utc>>,
203 pub finished_at: Option<DateTime<Utc>>,
204 pub stage: JobStage,
205 pub progress_done: Option<i64>,
206 pub progress_total: Option<i64>,
207 pub progress_pct: Option<f64>,
208 pub checkpoint: Option<Value>,
209 pub output: Option<Value>,
210 pub idempotency_key: Option<String>,
211 pub status_reason: Option<String>,
212 pub last_error_code: Option<String>,
213 pub last_error_message: Option<String>,
214 pub created_at: DateTime<Utc>,
215 pub updated_at: DateTime<Utc>,
216}
217
218#[derive(Debug, Clone)]
219pub struct JobEventRecord {
220 pub id: i64,
221 pub job_id: Uuid,
222 pub run_number: i32,
223 pub attempt: Option<i32>,
224 pub event_type: JobEventType,
225 pub stage: Option<JobStage>,
226 pub progress_done: Option<i64>,
227 pub progress_total: Option<i64>,
228 pub payload: Value,
229 pub occurred_at: DateTime<Utc>,
230}
231
232#[derive(Debug, Clone, PartialEq, Eq)]
233pub struct ReapedTerminalLeaseRecord {
234 pub job_id: Uuid,
235 pub job_type: JobTypeName,
236 pub organization_id: Option<Uuid>,
237 pub run_number: i32,
238 pub attempt: i32,
239 pub payload: Value,
240}
241
242#[non_exhaustive]
243#[derive(Debug, Clone, PartialEq, Eq)]
244pub enum ReapedLeaseDisposition {
245 ReleasedToPending,
246 RetryScheduled {
247 retry_delay_ms: i32,
248 next_run_at: DateTime<Utc>,
249 },
250 DeadLetteredTerminal {
251 payload: Value,
252 },
253}
254
255#[non_exhaustive]
256#[derive(Debug, Clone)]
257pub struct ReapedLeaseRecord {
258 pub job_id: Uuid,
259 pub job_type: JobTypeName,
260 pub organization_id: Option<Uuid>,
261 pub run_number: i32,
262 pub attempt: i32,
263 pub max_attempts: i32,
264 pub worker_id: Option<String>,
265 pub started_without_renewal_heartbeat: bool,
266 pub failure: JobFailure,
267 pub disposition: ReapedLeaseDisposition,
268}
269
270#[non_exhaustive]
271#[derive(Debug, Clone)]
272pub struct ReapExpiredLeaseDeferredError {
273 pub job_id: Uuid,
274 pub run_number: i32,
275 pub attempt: i32,
276 pub error_code: String,
277 pub error_message: String,
278 pub sqlstate: Option<String>,
279}
280
281#[derive(Debug, Clone)]
282pub struct ReapExpiredLeasesResult {
283 pub processed: i64,
284 pub terminal_dead_lettered: Vec<ReapedTerminalLeaseRecord>,
285}
286
287#[non_exhaustive]
288#[derive(Debug, Clone)]
289pub struct ReapExpiredLeasesDetailedResult {
290 pub summary: ReapExpiredLeasesResult,
291 pub reaped_leases: Vec<ReapedLeaseRecord>,
292 pub deferred_row_error_count: usize,
293 pub deferred_row_errors: Vec<ReapExpiredLeaseDeferredError>,
294}
295
296#[derive(Debug, Clone)]
297pub struct JobMetricsRecord {
298 pub job_type: JobTypeName,
299 pub pending_count: i64,
300 pub leased_count: i64,
301 pub stale_leases: i64,
302 pub succeeded_24h: i64,
303 pub retryable_24h: i64,
304 pub terminal_24h: i64,
305 pub panicked_24h: i64,
306 pub timeout_24h: i64,
307 pub dead_lettered_24h: i64,
308 pub p50_duration_ms_24h: Option<f64>,
309 pub p95_duration_ms_24h: Option<f64>,
310}
311
312#[derive(Debug, Clone)]
313pub struct JobLogRecord {
314 pub id: i64,
315 pub job_id: Uuid,
316 pub run_number: i32,
317 pub attempt: Option<i32>,
318 pub level: String,
319 pub message: String,
320 pub payload: Value,
321 pub occurred_at: DateTime<Utc>,
322}
323
324#[derive(Debug, Clone)]
325pub struct JobLogRecordInput {
326 pub job_id: Uuid,
327 pub run_number: i32,
328 pub attempt: Option<i32>,
329 pub level: String,
330 pub message: String,
331 pub payload: Value,
332}
333
334#[derive(Debug, Clone)]
335pub struct JobProgressUpdate<'a> {
336 pub stage: Option<JobStage>,
337 pub progress_done: Option<i64>,
338 pub progress_total: Option<i64>,
339 pub checkpoint: Option<&'a Value>,
340}
341
342#[derive(Debug, Clone)]
343pub struct JobCompletionUpdate<'a> {
344 pub progress_done: Option<i64>,
345 pub progress_total: Option<i64>,
346 pub checkpoint: Option<&'a Value>,
347 pub output: Option<&'a Value>,
348}
349
350#[non_exhaustive]
351#[derive(Debug, Clone)]
352pub struct JobSuccessCompletionOutcome {
353 pub job_id: Uuid,
354 pub job_type: JobTypeName,
355 pub organization_id: Option<Uuid>,
356 pub run_number: i32,
357 pub attempt: i32,
358 pub max_attempts: i32,
359 pub progress_done: Option<i64>,
360 pub progress_total: Option<i64>,
361}
362
363#[derive(Debug, Clone)]
364pub struct JobFailureUpdate<'a> {
365 pub kind: JobFailureKind,
366 pub code: &'a str,
367 pub message: &'a str,
368 pub retry_delay_ms: Option<i32>,
369}
370
371#[non_exhaustive]
372#[derive(Debug, Clone, PartialEq, Eq)]
373pub enum JobFailureCompletionDisposition {
374 RetryScheduled {
375 retry_delay_ms: i32,
376 next_run_at: DateTime<Utc>,
377 },
378 DeadLettered {
379 reason: runledger_core::jobs::JobDeadLetterReason,
380 },
381}
382
383#[non_exhaustive]
384#[derive(Debug, Clone)]
385pub struct JobFailureCompletionOutcome {
386 pub job_id: Uuid,
387 pub job_type: JobTypeName,
388 pub organization_id: Option<Uuid>,
389 pub run_number: i32,
390 pub attempt: i32,
391 pub max_attempts: i32,
392 pub failure_kind: JobFailureKind,
393 pub failure_code: String,
394 pub failure_message: String,
395 pub disposition: JobFailureCompletionDisposition,
396}
397
398#[derive(Debug, Clone)]
399pub struct JobListFilter<'a> {
400 pub organization_id: Option<Uuid>,
401 pub status: Option<JobStatus>,
402 pub job_type: Option<&'a str>,
405 pub limit: i64,
406 pub offset: i64,
407}
408
409#[derive(Debug, Clone)]
410pub struct JobRuntimeConfigListFilter<'a> {
411 pub job_type: Option<&'a str>,
414 pub limit: i64,
415 pub offset: i64,
416}