118 lines
3.5 KiB
Rust
118 lines
3.5 KiB
Rust
use crate::{distro::MetaDistroMgr, Config, Global};
|
|
|
|
use std::{io, path::PathBuf, sync::Arc};
|
|
|
|
use axum::Router;
|
|
use clap::Parser;
|
|
use sea_orm_migration::MigratorTrait;
|
|
use tower_http::trace::TraceLayer;
|
|
use tracing::debug;
|
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
|
|
|
#[derive(Parser)]
|
|
#[command(author, version, about, long_about = None)]
|
|
pub struct Cli {
|
|
/// Directory where repository metadata & SQLite database is stored
|
|
#[arg(env = "RIETER_DATA_DIR")]
|
|
pub data_dir: PathBuf,
|
|
/// API key to authenticate private routes with
|
|
#[arg(env = "RIETER_API_KEY")]
|
|
pub api_key: String,
|
|
|
|
#[arg(
|
|
short,
|
|
long,
|
|
env = "RIETER_CONFIG_FILE",
|
|
default_value = "./rieterd.toml"
|
|
)]
|
|
pub config_file: PathBuf,
|
|
|
|
/// Database connection URL; either sqlite:// or postgres://. Defaults to rieter.sqlite in the
|
|
/// data directory
|
|
#[arg(short, long, env = "RIETER_DATABASE_URL")]
|
|
pub database_url: Option<String>,
|
|
/// Port the server will listen on
|
|
#[arg(
|
|
short,
|
|
long,
|
|
value_name = "PORT",
|
|
default_value_t = 8000,
|
|
env = "RIETER_PORT"
|
|
)]
|
|
pub port: u16,
|
|
/// Log levels for the tracing
|
|
#[arg(
|
|
long,
|
|
value_name = "LOG_LEVEL",
|
|
default_value = "tower_http=debug,rieterd=debug",
|
|
env = "RIETER_LOG"
|
|
)]
|
|
pub log: String,
|
|
}
|
|
|
|
impl Cli {
|
|
pub fn init_tracing(&self) {
|
|
tracing_subscriber::registry()
|
|
.with(tracing_subscriber::EnvFilter::new(self.log.clone()))
|
|
.with(tracing_subscriber::fmt::layer())
|
|
.init();
|
|
}
|
|
|
|
pub async fn run(&self) -> crate::Result<()> {
|
|
self.init_tracing();
|
|
|
|
//tracing::debug!("{:?}", &self.config_file);
|
|
//let new_config: crate::config::Config = crate::config::Config::figment(&self.config_file).extract().inspect_err(
|
|
// |e| tracing::error!("{}", e)
|
|
//)?;
|
|
//tracing::debug!("{:?}", new_config);
|
|
|
|
let db_url = if let Some(url) = &self.database_url {
|
|
url.clone()
|
|
} else {
|
|
format!(
|
|
"sqlite://{}?mode=rwc",
|
|
self.data_dir.join("rieter.sqlite").to_string_lossy()
|
|
)
|
|
};
|
|
|
|
debug!("Connecting to database with URL {}", db_url);
|
|
|
|
let mut options = sea_orm::ConnectOptions::new(db_url);
|
|
options.max_connections(16);
|
|
|
|
let db = sea_orm::Database::connect(options).await?;
|
|
crate::db::Migrator::up(&db, None).await?;
|
|
|
|
debug!("Successfully applied migrations");
|
|
|
|
let config = Config {
|
|
data_dir: self.data_dir.clone(),
|
|
};
|
|
|
|
let mgr = Arc::new(crate::repo::RepoMgr::new(&self.data_dir.join("repos"), db.clone()).await?);
|
|
|
|
for _ in 0..1 {
|
|
let clone = Arc::clone(&mgr);
|
|
|
|
tokio::spawn(async move { clone.pkg_parse_task().await });
|
|
}
|
|
|
|
let global = Global { config, mgr, db };
|
|
|
|
// build our application with a single route
|
|
let app = Router::new()
|
|
.nest("/api", crate::api::router())
|
|
.merge(crate::repo::router(&self.api_key))
|
|
.with_state(global)
|
|
.layer(TraceLayer::new_for_http());
|
|
|
|
let domain: String = format!("0.0.0.0:{}", self.port).parse().unwrap();
|
|
let listener = tokio::net::TcpListener::bind(domain).await?;
|
|
// run it with hyper on localhost:3000
|
|
Ok(axum::serve(listener, app.into_make_service())
|
|
.await
|
|
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?)
|
|
}
|
|
}
|