107 lines
2.7 KiB
Rust
107 lines
2.7 KiB
Rust
use {
|
|
tower_http::{services::ServeDir, trace::TraceLayer},
|
|
tracing::Level,
|
|
};
|
|
|
|
mod app;
|
|
mod authentication;
|
|
mod config;
|
|
mod db;
|
|
mod error;
|
|
|
|
use config::get_config;
|
|
use db::{Database, PostgresDatabase};
|
|
|
|
|
|
/// An unrecoverable error which requires the server to shut down
|
|
#[derive(Debug)]
|
|
struct FatalError {
|
|
message: &'static str,
|
|
inner: Option<Box<dyn std::error::Error>>,
|
|
}
|
|
|
|
impl std::fmt::Display for FatalError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match &self.inner {
|
|
Some(inner_err) => write!(f, "{}: {}", self.message, inner_err),
|
|
None => write!(f, "{}", self.message),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for FatalError {
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
self.inner.as_deref()
|
|
}
|
|
}
|
|
|
|
impl From<config::Error> for FatalError {
|
|
fn from(value: config::Error) -> Self {
|
|
FatalError {
|
|
message: "Loading config",
|
|
inner: Some(Box::new(value)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<tracing::subscriber::SetGlobalDefaultError> for FatalError {
|
|
fn from(value: tracing::subscriber::SetGlobalDefaultError) -> Self {
|
|
FatalError {
|
|
message: "Loading config",
|
|
inner: Some(Box::new(value)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<db::InitialisationError> for FatalError {
|
|
fn from(value: db::InitialisationError) -> Self {
|
|
FatalError {
|
|
message: "initialising database connection",
|
|
inner: Some(Box::new(value)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<std::io::Error> for FatalError {
|
|
fn from(value: std::io::Error) -> Self {
|
|
FatalError {
|
|
message: "Initialising",
|
|
inner: Some(Box::new(value)),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let runtime = tokio::runtime::Runtime::new().unwrap();
|
|
std::process::exit(match runtime.block_on(locality_main()) {
|
|
Ok(()) => 0,
|
|
Err(err) => {
|
|
eprintln!("ERROR: {}", err);
|
|
1
|
|
}
|
|
})
|
|
}
|
|
|
|
async fn locality_main() -> Result<(), FatalError> {
|
|
let config = get_config()?;
|
|
|
|
let subscriber = tracing_subscriber::FmtSubscriber::builder()
|
|
.pretty()
|
|
.with_max_level(Level::DEBUG)
|
|
.finish();
|
|
tracing::subscriber::set_global_default(subscriber)?;
|
|
|
|
let db_pool = PostgresDatabase::new(&config.database_url)?;
|
|
|
|
db_pool.migrate_to_current_version().await.unwrap();
|
|
|
|
let app = app::routes()
|
|
.with_state(app::AppState { db: db_pool })
|
|
.nest_service("/static", ServeDir::new(&config.static_file_path))
|
|
.layer(TraceLayer::new_for_http());
|
|
|
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
|
|
axum::serve(listener, app).await?;
|
|
Ok(())
|
|
}
|