Files
web-template-rs/src/main.rs

86 lines
2.4 KiB
Rust
Raw Normal View History

2024-10-14 20:21:19 +02:00
use core::panic;
use std::str::FromStr;
use std::{env, fmt::Display};
use tokio::signal::unix::{signal, SignalKind};
use tokio_util::sync::CancellationToken;
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
use web_template::Config;
2024-04-21 23:02:59 +02:00
2024-10-14 20:21:19 +02:00
#[tokio::main]
async fn main() -> Result<(), String> {
// Enable logging in JSON format
2024-04-21 23:02:59 +02:00
tracing_subscriber::registry()
2024-10-14 20:21:19 +02:00
.with(fmt::layer().json())
.with(EnvFilter::from_env("LOG_LEVEL"))
2024-04-21 23:02:59 +02:00
.init();
2024-10-14 20:21:19 +02:00
// On panic format the message as JSON before exit
std::panic::set_hook(Box::new(|panic_info| {
let location = panic_info
.location()
.map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column()))
.unwrap_or_else(|| "unknown location".to_string());
2024-04-21 23:02:59 +02:00
2024-10-14 20:21:19 +02:00
let message = match panic_info.payload().downcast_ref::<String>() {
Some(s) => s,
None => "unknown message",
};
2024-04-21 23:02:59 +02:00
2024-10-14 20:21:19 +02:00
tracing::error!("Panic occured at {}: {}", location, message)
}));
// Parse environment variables and create a Config struct
let config = Config {
listen_port: parse_env("LISTEN_PORT", 8080),
};
2024-04-21 23:02:59 +02:00
2024-10-14 20:21:19 +02:00
let (Ok(mut sigterm), Ok(mut sigint)) = (
signal(SignalKind::terminate()),
signal(SignalKind::interrupt()),
) else {
panic!("Failed to install signal handlers");
};
2024-04-21 23:02:59 +02:00
2024-10-14 20:21:19 +02:00
// A token to be used to signal a shutdown request
let token = CancellationToken::new();
2024-04-21 23:02:59 +02:00
2024-10-14 20:21:19 +02:00
let mut webserver_handle = tokio::spawn(web_template::run(config, token.clone()));
tokio::select! {
_ = sigterm.recv() => {
tracing::info!("Received SIGTERM");
token.cancel();
},
_ = sigint.recv() => {
tracing::info!("Received SIGINT");
token.cancel();
},
_ = &mut webserver_handle => {},
};
let _ = webserver_handle.await;
Ok(())
}
2024-04-21 23:02:59 +02:00
2024-10-14 20:21:19 +02:00
fn parse_env<T>(env_name: &str, default: T) -> T
where
T: Display + FromStr,
<T as FromStr>::Err: std::fmt::Display,
{
let Ok(env_value) = env::var(env_name) else {
tracing::info!("Environment variable '{env_name}' not set, using default {default}");
return default;
};
2024-04-21 23:02:59 +02:00
2024-10-14 20:21:19 +02:00
str::parse(&env_value).unwrap_or_else(|e| {
let msg = format!(
"Environment variable '{}' could not be converted to type {}: {}",
env_name,
std::any::type_name::<T>(),
e
);
2024-04-21 23:02:59 +02:00
2024-10-14 20:21:19 +02:00
panic!("{}", msg);
})
2024-04-21 23:02:59 +02:00
}