kbolt_core/engine/
schedule_status_ops.rs1use crate::error::CoreError;
2use crate::lock::LockMode;
3use crate::schedule_backend::{current_schedule_backend, inspect_schedule_backend};
4use crate::schedule_state_store::ScheduleRunStateStore;
5use crate::schedule_store::ScheduleCatalog;
6use crate::schedule_support::schedule_id_sort_key;
7use crate::Result;
8use kbolt_types::{
9 KboltError, ScheduleOrphan, ScheduleScope, ScheduleState, ScheduleStatusEntry,
10 ScheduleStatusResponse,
11};
12
13use super::Engine;
14
15impl Engine {
16 pub fn schedule_status(&self) -> Result<ScheduleStatusResponse> {
17 let _lock = self.acquire_operation_lock(LockMode::Shared)?;
18 let backend = current_schedule_backend()?;
19 let mut schedules = ScheduleCatalog::load(&self.config.config_dir)?.schedules;
20 schedules.sort_by_key(|schedule| schedule_id_sort_key(&schedule.id));
21
22 let inspection =
23 inspect_schedule_backend(&self.config.config_dir, &self.config.cache_dir, &schedules)?;
24 let mut entries = Vec::with_capacity(schedules.len());
25
26 for schedule in schedules {
27 let state = if self.schedule_targets_missing(&schedule.scope)? {
28 ScheduleState::TargetMissing
29 } else if inspection.drifted_ids.contains(&schedule.id) {
30 ScheduleState::Drifted
31 } else {
32 ScheduleState::Installed
33 };
34
35 let run_state = ScheduleRunStateStore::load(&self.config.cache_dir, &schedule.id)?;
36 entries.push(ScheduleStatusEntry {
37 schedule,
38 backend,
39 state,
40 run_state,
41 });
42 }
43
44 let orphans = inspection
45 .orphan_ids
46 .into_iter()
47 .map(|id| ScheduleOrphan { id, backend })
48 .collect();
49
50 Ok(ScheduleStatusResponse {
51 schedules: entries,
52 orphans,
53 })
54 }
55
56 fn schedule_targets_missing(&self, scope: &ScheduleScope) -> Result<bool> {
57 match scope {
58 ScheduleScope::All => Ok(false),
59 ScheduleScope::Space { space } => match self.storage.get_space(space) {
60 Ok(_) => Ok(false),
61 Err(CoreError::Domain(KboltError::SpaceNotFound { .. })) => Ok(true),
62 Err(err) => Err(err),
63 },
64 ScheduleScope::Collections { space, collections } => {
65 let resolved_space = match self.storage.get_space(space) {
66 Ok(space) => space,
67 Err(CoreError::Domain(KboltError::SpaceNotFound { .. })) => return Ok(true),
68 Err(err) => return Err(err),
69 };
70
71 for collection in collections {
72 match self.storage.get_collection(resolved_space.id, collection) {
73 Ok(_) => {}
74 Err(CoreError::Domain(KboltError::CollectionNotFound { .. })) => {
75 return Ok(true)
76 }
77 Err(err) => return Err(err),
78 }
79 }
80
81 Ok(false)
82 }
83 }
84 }
85}