systemprompt_provider_contracts/
job.rs1use anyhow::Result;
2use async_trait::async_trait;
3use std::collections::HashMap;
4use std::sync::Arc;
5
6#[derive(Debug, Clone)]
7pub struct JobResult {
8 pub success: bool,
9 pub message: Option<String>,
10 pub items_processed: Option<u64>,
11 pub items_failed: Option<u64>,
12 pub duration_ms: u64,
13}
14
15impl JobResult {
16 pub const fn success() -> Self {
17 Self {
18 success: true,
19 message: None,
20 items_processed: None,
21 items_failed: None,
22 duration_ms: 0,
23 }
24 }
25
26 pub fn with_message(mut self, message: impl Into<String>) -> Self {
27 self.message = Some(message.into());
28 self
29 }
30
31 pub const fn with_stats(mut self, processed: u64, failed: u64) -> Self {
32 self.items_processed = Some(processed);
33 self.items_failed = Some(failed);
34 self
35 }
36
37 pub const fn with_duration(mut self, duration_ms: u64) -> Self {
38 self.duration_ms = duration_ms;
39 self
40 }
41
42 pub fn failure(message: impl Into<String>) -> Self {
43 Self {
44 success: false,
45 message: Some(message.into()),
46 items_processed: None,
47 items_failed: None,
48 duration_ms: 0,
49 }
50 }
51}
52
53pub struct JobContext {
54 db_pool: Arc<dyn std::any::Any + Send + Sync>,
55 app_context: Arc<dyn std::any::Any + Send + Sync>,
56 parameters: HashMap<String, String>,
57}
58
59impl std::fmt::Debug for JobContext {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 f.debug_struct("JobContext")
62 .field("db_pool", &"<type-erased>")
63 .field("app_context", &"<type-erased>")
64 .field("parameters", &self.parameters)
65 .finish()
66 }
67}
68
69impl JobContext {
70 pub fn new(
71 db_pool: Arc<dyn std::any::Any + Send + Sync>,
72 app_context: Arc<dyn std::any::Any + Send + Sync>,
73 ) -> Self {
74 Self {
75 db_pool,
76 app_context,
77 parameters: HashMap::new(),
78 }
79 }
80
81 pub fn with_parameters(mut self, parameters: HashMap<String, String>) -> Self {
82 self.parameters = parameters;
83 self
84 }
85
86 pub fn db_pool<T: 'static>(&self) -> Option<&T> {
87 self.db_pool.as_ref().downcast_ref::<T>()
88 }
89
90 pub fn app_context<T: 'static>(&self) -> Option<&T> {
91 self.app_context.as_ref().downcast_ref::<T>()
92 }
93
94 pub fn db_pool_arc(&self) -> Arc<dyn std::any::Any + Send + Sync> {
95 Arc::clone(&self.db_pool)
96 }
97
98 pub fn app_context_arc(&self) -> Arc<dyn std::any::Any + Send + Sync> {
99 Arc::clone(&self.app_context)
100 }
101
102 pub const fn parameters(&self) -> &HashMap<String, String> {
103 &self.parameters
104 }
105
106 pub fn get_parameter(&self, key: &str) -> Option<&String> {
107 self.parameters.get(key)
108 }
109}
110
111#[async_trait]
112pub trait Job: Send + Sync + 'static {
113 fn name(&self) -> &'static str;
114
115 fn description(&self) -> &'static str {
116 ""
117 }
118
119 fn schedule(&self) -> &'static str;
120
121 fn tags(&self) -> Vec<&'static str> {
122 vec![]
123 }
124
125 async fn execute(&self, ctx: &JobContext) -> Result<JobResult>;
126
127 fn enabled(&self) -> bool {
128 true
129 }
130
131 fn run_on_startup(&self) -> bool {
132 false
133 }
134}
135
136inventory::collect!(&'static dyn Job);
137
138#[macro_export]
139macro_rules! submit_job {
140 ($job:expr) => {
141 inventory::submit!($job as &'static dyn $crate::Job);
142 };
143}