use sysf::registry::{DependencyTree, Registry}; use sysf::unit::UnitState; use std::collections::HashMap; use sysf::config::loader::Loader; use sysf::utils::asyn::AsyncQueue; use async_std::prelude::StreamExt; use async_std::task; use crate::manager::ManagerSignal::*; use async_std::sync::{Arc, Mutex, MutexGuard}; #[derive(Clone, Debug)] pub enum ManagerSignal { TargetUpdate(String), Noop, } impl Default for ManagerSignal { fn default() -> Self { Noop } } #[derive(Clone, Default, Debug)] pub struct Manager { state: Arc>, queue: AsyncQueue, } #[derive(Clone, Default, Debug)] pub struct ManagerState { dependency_tree: DependencyTree, unit_status: HashMap, registry: Registry, queue: AsyncQueue, } impl Manager { pub fn new(loader: Loader) -> Manager { let queue = AsyncQueue::new(); Manager { state: Arc::new(Mutex::new(ManagerState { dependency_tree: DependencyTree::default(), unit_status: HashMap::new(), registry: Registry::with_loader(loader), queue: queue.clone(), })), queue, } } pub async fn with(&mut self, block: F) where F: FnOnce(MutexGuard) { block(self.state.lock().await) } pub fn target(&mut self, target: &str) { self.queue.push(ManagerSignal::TargetUpdate(target.to_string())); } pub fn signal(&mut self, signal: ManagerSignal) { self.queue.push(signal); } pub async fn run(&mut self) { while let Some(signal) = self.queue.next().await { let mut copy: Manager = self.clone(); task::spawn(async { match signal { TargetUpdate(target) => { copy.update_target(target).await; } _ => {} } }); } } pub fn get_remote(&self) -> ManagerRemote { ManagerRemote(self.queue.clone()) } async fn update_target(mut self, target: String) { let mut me = self.state.lock().await; let tree = me.registry.get_dependency_tree(&target).await; me.dependency_tree = tree; } } pub struct ManagerRemote(AsyncQueue); impl ManagerRemote { pub fn signal(&mut self, signal: ManagerSignal) { self.0.push(signal); } }