mod health; mod routes; use clap::Parser; use dotenv::dotenv; use eyre::Context; use health::HealthState; use rocket::fs::FileServer; use rocket_dyn_templates::Template; use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; use tokio::{fs, task, time::sleep}; #[derive(Parser)] struct Opt { /// Path to the config file. #[clap(short, long, env = "CONFIG_PATH", default_value = "config.ron")] config: PathBuf, } #[rocket::main] async fn main() -> eyre::Result<()> { dotenv().ok(); let opt = Opt::parse(); color_eyre::install()?; let config = fs::read_to_string(&opt.config) .await .wrap_err_with(|| format!("failed to read config file: {:?}", opt.config))?; let config = ron::from_str(&config) .wrap_err_with(|| format!("failed to parse config file: {:?}", opt.config))?; let state = Arc::new(HealthState::new(config)); let rocket = rocket::build() .attach(Template::fairing()) .manage(Arc::clone(&state)) .mount("/static", FileServer::from("static")) .mount("/", rocket::routes![routes::pages::dashboard]); start_poller(state); rocket.launch().await.wrap_err("rocket failed to launch")?; Ok(()) } fn start_poller(state: Arc) { task::spawn(async move { loop { state.update().await; sleep(Duration::from_secs(state.config.update_period)).await; } }); }