#![deny(warnings)]
mod cli;
mod cron_jobs;
mod error;
mod filesystem;
mod middlewares;
mod openapi;
mod paths;
mod routes;
mod routine_storage;
mod routines;
mod storage;
mod sync;
mod utils;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
match cli::parse(std::env::args().skip(1)) {
cli::Command::Help => {
cli::print_help();
Ok(())
}
cli::Command::Version => {
cli::print_version();
Ok(())
}
cli::Command::Status => cli::status(),
cli::Command::Stop => cli::stop(),
cli::Command::Background => cli::run_background(),
cli::Command::Foreground => run_server().await,
}
}
async fn run_server() -> anyhow::Result<()> {
routines::ensure_default_agents();
let store = storage::load_store();
let routines = routine_storage::load_store();
if let Err(e) = sync::routines::sync_routines_to_crontab(&routines) {
log::warn!("startup crontab sync failed: {e}");
}
let listener = tokio::net::TcpListener::bind(cli::BIND_ADDR).await?;
cli::write_pid_file()?;
let result =
routes::http::run_with_listener_until(store, routines, listener, termination_signal())
.await;
cli::clear_pid_file();
result
}
async fn termination_signal() {
#[cfg(unix)]
{
use tokio::signal::unix::{signal, SignalKind};
match signal(SignalKind::terminate()) {
Ok(mut term) => {
tokio::select! {
_ = tokio::signal::ctrl_c() => {}
_ = term.recv() => {}
}
}
Err(_) => {
let _ = tokio::signal::ctrl_c().await;
}
}
}
#[cfg(not(unix))]
{
let _ = tokio::signal::ctrl_c().await;
}
}