use std::{fs::File, path::Path};
mod activity;
mod conditions;
mod config;
mod prelude;
mod service;
mod task;
mod triggers;
mod utils;
use prelude::*;
struct Daemon {
tasks: Vec<Task>,
services: Vec<Service>,
}
impl Daemon {
fn parse(path: impl AsRef<Path>) -> Result<Daemon> {
let path = path.as_ref();
if path.exists() {
let config: config::Config = serde_yaml_ng::from_reader(File::open(path)?)?;
let tasks = config
.tasks
.into_iter()
.map(Task::new)
.collect::<Result<_>>()?;
let services = config
.services
.into_iter()
.map(Service::new)
.collect::<Result<_>>()?;
Ok(Daemon { tasks, services })
} else {
Err(anyhow::anyhow!(
"Missing configuration file at '{:?}'.",
path
))
}
}
}
#[tokio::main]
async fn main() {
env_logger::builder()
.filter_level(log::LevelFilter::Info)
.parse_default_env()
.init();
let dirs = directories::ProjectDirs::from("com", "cyloncore", "userd").unwrap();
let config_path = dirs.config_dir().join("config");
loop {
let daemon = Daemon::parse(&config_path);
match daemon {
Ok(daemon) => {
log::info!("Success!");
let tasks: Vec<_> = daemon
.tasks
.into_iter()
.map(|task| tokio::spawn(task.start()))
.collect();
let services: Vec<_> = daemon
.services
.into_iter()
.map(|service| tokio::spawn(service.start()))
.collect();
utils::async_watch(config_path.clone()).await.unwrap();
for t in tasks {
t.abort();
}
for s in services {
s.abort();
}
}
Err(e) => {
log::error!("Failure to start daemon: {:?}", e);
utils::async_watch(config_path.clone()).await.unwrap();
}
}
}
}