use crate::utils::lock::LockRecover;
use uuid::Uuid;
use crate::routine_storage::write_routine;
use crate::utils::cron::normalize_schedule;
use crate::utils::time::now_secs;
use super::command::slugify;
use super::model::{Routine, RoutineStore};
mod the_1_percent;
mod token_trim;
mod update_moadim;
struct DefaultRoutine {
title: &'static str,
schedule: &'static str,
agent: &'static str,
prompt: &'static str,
}
const DEFAULT_ROUTINES: &[DefaultRoutine] =
&[update_moadim::SPEC, the_1_percent::SPEC, token_trim::SPEC];
fn materialize(spec: &DefaultRoutine, now: u64) -> Routine {
Routine {
id: Uuid::new_v4().to_string(),
schedule: normalize_schedule(spec.schedule),
title: spec.title.to_string(),
agent: spec.agent.to_string(),
prompt: spec.prompt.to_string(),
repositories: Vec::new(),
machines: vec![crate::machine::current_machine()],
enabled: true,
source: "managed".to_string(),
created_at: now,
updated_at: now,
last_manual_trigger_at: None,
last_scheduled_trigger_at: None,
ttl_secs: None,
max_runtime_secs: None,
tags: Vec::new(),
}
}
fn reconcile(spec: &DefaultRoutine, cur: &Routine, now: u64) -> Option<Routine> {
let schedule = normalize_schedule(spec.schedule);
let up_to_date = cur.schedule == schedule
&& cur.agent == spec.agent
&& cur.prompt == spec.prompt
&& cur.repositories.is_empty();
if up_to_date {
return None;
}
Some(Routine {
id: cur.id.clone(),
schedule,
title: spec.title.to_string(),
agent: spec.agent.to_string(),
prompt: spec.prompt.to_string(),
repositories: Vec::new(),
machines: cur.machines.clone(),
enabled: cur.enabled,
source: "managed".to_string(),
created_at: cur.created_at,
updated_at: now,
last_manual_trigger_at: cur.last_manual_trigger_at,
last_scheduled_trigger_at: cur.last_scheduled_trigger_at,
ttl_secs: cur.ttl_secs,
max_runtime_secs: cur.max_runtime_secs,
tags: cur.tags.clone(),
})
}
pub fn ensure_default_routines(store: &RoutineStore) {
for spec in DEFAULT_ROUTINES {
let slug = slugify(spec.title);
let existing = store
.lock_recover()
.values()
.find(|routine| slugify(&routine.title) == slug)
.cloned();
let routine = match existing {
Some(cur) => match reconcile(spec, &cur, now_secs()) {
Some(updated) => updated,
None => continue,
},
None => materialize(spec, now_secs()),
};
if let Err(err) = write_routine(&routine) {
log::warn!(
"ensure_default_routines: failed to write {:?}: {err}; skipping",
spec.title
);
continue;
}
store.lock_recover().insert(routine.id.clone(), routine);
}
}
#[cfg(test)]
#[path = "mod_tests.rs"]
mod defaults_tests;