69 lines
1.9 KiB
Rust
69 lines
1.9 KiB
Rust
use std::path::Path;
|
|
use std::sync::Arc;
|
|
|
|
use desi_explorer_api::{config, routes, store};
|
|
|
|
use tracing_subscriber::EnvFilter;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter(
|
|
EnvFilter::try_from_default_env()
|
|
.unwrap_or_else(|_| EnvFilter::new("desi_explorer_api=info")),
|
|
)
|
|
.init();
|
|
|
|
load_env_file()?;
|
|
|
|
let config = config::Config::from_env()?;
|
|
|
|
let catalog_store = match &config.desi_data {
|
|
Some(path) => {
|
|
tracing::info!(path = %path.display(), "loading DESI data");
|
|
store::CatalogStore::load(Path::new(path))?
|
|
}
|
|
None => {
|
|
tracing::warn!("API_DESI_DATA not set, serving placeholder catalogs");
|
|
store::CatalogStore::placeholder()
|
|
}
|
|
};
|
|
|
|
let app = routes::app_with_state(Arc::new(catalog_store));
|
|
|
|
let listener = tokio::net::TcpListener::bind(&config.bind_addr).await?;
|
|
tracing::info!("DESI Explorer API listening on {}", config.bind_addr);
|
|
|
|
axum::serve(listener, app)
|
|
.with_graceful_shutdown(shutdown_signal())
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Loads the env file named by `API_ENV_FILE` (if set) into the process
|
|
/// environment. Existing env vars are not overridden, so values passed
|
|
/// directly on the command line or by the Makefile take precedence.
|
|
fn load_env_file() -> anyhow::Result<()> {
|
|
let path = std::env::var("API_ENV_FILE").unwrap_or_default();
|
|
if path.is_empty() {
|
|
return Ok(());
|
|
}
|
|
|
|
match dotenvy::from_path(&path) {
|
|
Ok(_) => tracing::info!(%path, "loaded env file"),
|
|
Err(err) => {
|
|
return Err(anyhow::anyhow!(
|
|
"failed to load API_ENV_FILE {path:?}: {err}"
|
|
))
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn shutdown_signal() {
|
|
let _ = tokio::signal::ctrl_c().await;
|
|
tracing::info!("shutting down");
|
|
}
|