Skip to main content

systemprompt_models/services/
scheduler.rs

1//! Scheduler job configuration and the built-in job set.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use std::collections::HashMap;
7
8use serde::{Deserialize, Serialize};
9use systemprompt_identifiers::UserId;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12#[serde(deny_unknown_fields)]
13pub struct JobConfig {
14    #[serde(default)]
15    pub extension: Option<String>,
16    pub name: String,
17    #[serde(default)]
18    pub owner: Option<UserId>,
19    #[serde(default = "default_true")]
20    pub enabled: bool,
21    #[serde(default)]
22    pub schedule: Option<String>,
23    #[serde(default)]
24    pub enforce: bool,
25    #[serde(default)]
26    pub parameters: HashMap<String, String>,
27}
28
29const fn default_true() -> bool {
30    true
31}
32
33impl JobConfig {
34    #[must_use]
35    pub fn new(name: impl Into<String>) -> Self {
36        Self {
37            extension: None,
38            name: name.into(),
39            owner: None,
40            enabled: true,
41            schedule: None,
42            enforce: false,
43            parameters: HashMap::new(),
44        }
45    }
46
47    #[must_use]
48    pub const fn with_enforce(mut self) -> Self {
49        self.enforce = true;
50        self
51    }
52
53    #[must_use]
54    pub fn with_owner(mut self, owner: UserId) -> Self {
55        self.owner = Some(owner);
56        self
57    }
58
59    #[must_use]
60    pub fn with_extension(mut self, extension: impl Into<String>) -> Self {
61        self.extension = Some(extension.into());
62        self
63    }
64
65    #[must_use]
66    pub fn with_schedule(mut self, schedule: impl Into<String>) -> Self {
67        self.schedule = Some(schedule.into());
68        self
69    }
70
71    #[must_use]
72    pub fn with_parameters(mut self, parameters: HashMap<String, String>) -> Self {
73        self.parameters = parameters;
74        self
75    }
76
77    #[must_use]
78    pub const fn disabled(mut self) -> Self {
79        self.enabled = false;
80        self
81    }
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct SchedulerConfig {
86    #[serde(default = "default_true")]
87    pub enabled: bool,
88    #[serde(default)]
89    pub jobs: Vec<JobConfig>,
90    #[serde(default = "default_bootstrap_jobs")]
91    pub bootstrap_jobs: Vec<String>,
92    #[serde(default = "default_true")]
93    pub distributed_lock: bool,
94}
95
96fn default_bootstrap_jobs() -> Vec<String> {
97    vec!["cleanup_inactive_sessions".to_owned()]
98}
99
100impl SchedulerConfig {
101    #[must_use]
102    pub fn with_system_admin() -> Self {
103        Self {
104            enabled: true,
105            jobs: vec![
106                JobConfig::new("cleanup_anonymous_users")
107                    .with_extension("core")
108                    .with_schedule("0 0 3 * * *")
109                    .with_enforce(),
110                JobConfig::new("cleanup_empty_contexts")
111                    .with_extension("core")
112                    .with_schedule("0 0 * * * *")
113                    .with_enforce(),
114                JobConfig::new("cleanup_inactive_sessions")
115                    .with_extension("core")
116                    .with_schedule("0 0 * * * *"),
117                JobConfig::new("database_cleanup")
118                    .with_extension("core")
119                    .with_schedule("0 0 4 * * *")
120                    .with_enforce(),
121            ],
122            bootstrap_jobs: default_bootstrap_jobs(),
123            distributed_lock: true,
124        }
125    }
126}