mur_common/
schedule_claim.rs1use std::path::{Path, PathBuf};
7
8use crate::schedule::{Schedule, ScheduleExecutor, SchedulesFile};
9
10pub fn commander_pid_path() -> PathBuf {
12 dirs::home_dir()
13 .unwrap_or_default()
14 .join(".mur")
15 .join("commander")
16 .join("commander.pid")
17}
18
19pub fn is_commander_running() -> bool {
21 is_commander_running_at(&commander_pid_path())
22}
23
24pub fn is_commander_running_at(pid_path: &Path) -> bool {
26 let content = match std::fs::read_to_string(pid_path) {
27 Ok(c) => c,
28 Err(_) => return false,
29 };
30
31 let pid: u32 = match content.trim().parse() {
32 Ok(p) => p,
33 Err(_) => return false,
34 };
35
36 crate::lock_file::pid_alive(pid)
42}
43
44pub fn schedules_path() -> PathBuf {
46 dirs::home_dir()
47 .unwrap_or_default()
48 .join(".mur")
49 .join("schedules.yaml")
50}
51
52pub fn load_schedules() -> Result<Vec<Schedule>, Box<dyn std::error::Error>> {
54 let path = schedules_path();
55 if !path.exists() {
56 return Ok(Vec::new());
57 }
58 let content = std::fs::read_to_string(&path)?;
59 let file: SchedulesFile = serde_yaml::from_str(&content)?;
60 Ok(file.schedules)
61}
62
63pub fn save_schedules(schedules: &[Schedule]) -> Result<(), Box<dyn std::error::Error>> {
65 let path = schedules_path();
66 if let Some(parent) = path.parent() {
67 std::fs::create_dir_all(parent)?;
68 }
69 let file = SchedulesFile {
70 schedules: schedules.to_vec(),
71 };
72 let yaml = serde_yaml::to_string(&file)?;
73 std::fs::write(&path, yaml)?;
74 Ok(())
75}
76
77pub fn claim_all_for_commander() -> Result<Vec<String>, Box<dyn std::error::Error>> {
80 let mut schedules = load_schedules()?;
81 let mut claimed = Vec::new();
82
83 for schedule in &mut schedules {
84 if schedule.executor != ScheduleExecutor::Commander {
85 claimed.push(schedule.workflow.clone());
86 schedule.executor = ScheduleExecutor::Commander;
87 }
88 }
89
90 if !claimed.is_empty() {
91 save_schedules(&schedules)?;
92 }
93
94 Ok(claimed)
95}
96
97pub fn release_all_from_commander() -> Result<Vec<String>, Box<dyn std::error::Error>> {
100 let mut schedules = load_schedules()?;
101 let mut released = Vec::new();
102
103 for schedule in &mut schedules {
104 if schedule.executor == ScheduleExecutor::Commander {
105 released.push(schedule.workflow.clone());
106 schedule.executor = ScheduleExecutor::SystemCron;
107 }
108 }
109
110 if !released.is_empty() {
111 save_schedules(&schedules)?;
112 }
113
114 Ok(released)
115}
116
117pub fn auto_detect_executor() -> ScheduleExecutor {
120 if is_commander_running() {
121 ScheduleExecutor::Commander
122 } else {
123 ScheduleExecutor::SystemCron
124 }
125}