82 lines
1.6 KiB
Rust
82 lines
1.6 KiB
Rust
mod db;
|
|
mod api;
|
|
mod config;
|
|
mod up;
|
|
|
|
use config::Config;
|
|
use db::Database;
|
|
|
|
use clap::Parser;
|
|
|
|
|
|
#[derive(Parser)]
|
|
struct Cli {
|
|
/// path to storage file, if not given will operate in memory
|
|
storage: Option<String>,
|
|
|
|
/// path to config file
|
|
#[arg(short, long, default_value = "upp.toml")]
|
|
config: String,
|
|
|
|
/// host to bind api onto
|
|
#[arg(short, long, default_value = "127.0.0.1:7717")]
|
|
addr: String,
|
|
}
|
|
|
|
fn main() {
|
|
let cli = Cli::parse();
|
|
|
|
let raw_config = match std::fs::read_to_string(&cli.config) {
|
|
Ok(x) => x,
|
|
Err(e) => {
|
|
println!("could not read config: {e}");
|
|
return;
|
|
},
|
|
};
|
|
|
|
let config = match toml::from_str::<Config>(&raw_config) {
|
|
Ok(x) => x,
|
|
Err(e) => {
|
|
println!("invalid config file: {e}");
|
|
return;
|
|
},
|
|
};
|
|
|
|
let db = match Database::open(cli.storage.as_deref()) {
|
|
Ok(x) => x,
|
|
Err(e) => {
|
|
println!("could not connect do database: {e}");
|
|
return;
|
|
},
|
|
};
|
|
|
|
let mut runtime_builder = {
|
|
#[cfg(feature = "multi-thread")]
|
|
{
|
|
tokio::runtime::Builder::new_multi_thread()
|
|
}
|
|
|
|
#[cfg(not(feature = "multi-thread"))]
|
|
{
|
|
tokio::runtime::Builder::new_current_thread()
|
|
}
|
|
};
|
|
|
|
if let Err(e) = runtime_builder
|
|
.enable_all()
|
|
.build()
|
|
.expect("could not create tokio runtime")
|
|
.block_on(async move {
|
|
up::work(config.clone(), db.clone()).await?; // <<-- this spawns background workers
|
|
|
|
api::serve(config, db, &cli.addr).await?; // <<-- this blocks!
|
|
|
|
// TODO it's a bit weird that these two work so differently, can we make them more similar?
|
|
|
|
Ok::<(), Box<dyn std::error::Error>>(()) // ughhh
|
|
})
|
|
{
|
|
println!("event loop terminated with error: {e}");
|
|
eprintln!("{e:?}");
|
|
}
|
|
}
|