Skip to main content

kbolt_core/engine/
schedule_status_ops.rs

1use 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}