79 lines
2.1 KiB
Rust
79 lines
2.1 KiB
Rust
use std::{
|
|
fs,
|
|
future::IntoFuture,
|
|
path::{Path, PathBuf},
|
|
};
|
|
|
|
use clap::Parser;
|
|
|
|
use eyre::Context;
|
|
use tokio::{net::TcpListener, runtime as rt};
|
|
use tracing_subscriber::FmtSubscriber;
|
|
|
|
use vnj::{app::App, cfg, db::Db, notifies, state::State};
|
|
|
|
#[derive(Debug, Parser)]
|
|
pub struct Args {
|
|
/// Path to the TOML config.
|
|
#[clap(long, short)]
|
|
pub config: PathBuf,
|
|
}
|
|
|
|
async fn run(cfg: cfg::Root) -> eyre::Result<()> {
|
|
let listener = TcpListener::bind(cfg.http.listen)
|
|
.await
|
|
.wrap_err("failed to bind HTTP port")?;
|
|
|
|
let db = Db::from_root(&cfg.app.journal)?;
|
|
let notifies = notifies::make();
|
|
let app = App::new(db, notifies.clone())?;
|
|
let state = State::new(app, cfg)?;
|
|
|
|
let daemon = tokio::spawn(vnj::daemon::run(state.clone(), notifies.clone()));
|
|
let router = vnj::http::make(state.clone()).with_state(state);
|
|
|
|
tracing::info!("listening on {}", listener.local_addr()?);
|
|
let server = tokio::spawn(axum::serve(listener, router).into_future());
|
|
|
|
tokio::try_join!(daemon, server)
|
|
.wrap_err("error while running")?
|
|
.0?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn read_config(path: &Path) -> eyre::Result<cfg::Root> {
|
|
let contents = fs::read_to_string(path).wrap_err("failed to read")?;
|
|
let cfg: cfg::Root = toml::from_str(&contents).wrap_err("failed to parse TOML")?;
|
|
|
|
Ok(cfg)
|
|
}
|
|
|
|
fn setup_logger(level: cfg::LogLevel) -> eyre::Result<()> {
|
|
let level: Option<tracing::Level> = level.into();
|
|
let subscriber = FmtSubscriber::builder();
|
|
let subscriber = if let Some(level) = level {
|
|
subscriber.with_max_level(level)
|
|
} else {
|
|
subscriber.with_max_level(tracing::level_filters::LevelFilter::OFF)
|
|
};
|
|
let subscriber = subscriber.finish();
|
|
|
|
tracing::subscriber::set_global_default(subscriber)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn main() -> eyre::Result<()> {
|
|
let rt = rt::Builder::new_current_thread()
|
|
.enable_all()
|
|
.thread_name("vnj")
|
|
.build()
|
|
.wrap_err("failed to create tokio runtime")?;
|
|
let args = Args::parse();
|
|
let cfg = read_config(&args.config).wrap_err("failed to load the config")?;
|
|
|
|
setup_logger(cfg.app.log_level)?;
|
|
|
|
rt.block_on(run(cfg))
|
|
}
|