Env config
All checks were successful
CI / Check typos (push) Successful in 8s
CI / Check links (push) Successful in 6s
CI / Clippy (push) Successful in 51s
CI / Build and test (push) Successful in 1m7s
CI / Build container (push) Successful in 45s
CI / Deploy on waypoint (push) Successful in 42s

This commit is contained in:
2025-11-06 20:45:44 -08:00
parent 4091d8b486
commit 4d8093c4a3
10 changed files with 272 additions and 31 deletions

View File

@@ -17,3 +17,4 @@ tokio = { workspace = true }
axum = { workspace = true }
clap = { workspace = true }
anyhow = { workspace = true }
serde = { workspace = true }

View File

@@ -0,0 +1,106 @@
use serde::Deserialize;
use std::num::NonZeroUsize;
use toolbox::{
env::load_env,
logging::{LogFilterPreset, LoggingFormat, LoggingInitializer, LoggingTarget, LokiConfig},
};
use tracing::info;
#[derive(Deserialize, Clone)]
pub struct WebpageConfig {
#[serde(default)]
pub loglevel: LogFilterPreset,
#[serde(default)]
pub logformat: LoggingFormat,
#[serde(flatten)]
pub loki: Option<LokiConfig>,
// How many threads tokio should use
pub runtime_threads: Option<NonZeroUsize>,
pub blocking_threads: Option<NonZeroUsize>,
}
impl WebpageConfig {
pub fn load() -> Self {
let config_res = match load_env::<WebpageConfig>() {
Ok(x) => x,
#[expect(clippy::print_stdout)]
Err(err) => {
println!("Error while loading .env: {err}");
std::process::exit(1);
}
};
let config = config_res.get_config().clone();
info!(message = "Config loaded");
return config;
}
/*
pub fn init_logging_noloki(&self) {
let res = LoggingInitializer {
app_name: "betalupi-webpage",
loki: None,
preset: self.loglevel,
target: LoggingTarget::Stderr {
format: self.logformat,
},
}
.initialize();
if let Err(e) = res {
#[expect(clippy::print_stderr)]
for e in e.chain() {
eprintln!("{e}");
}
std::process::exit(1);
}
}
*/
/// Must be run inside a tokio context,
/// use `init_logging_noloki` if you don't have async.
pub async fn init_logging(&self) {
let res = LoggingInitializer {
app_name: "betalupi-webpage",
loki: self.loki.clone(),
preset: self.loglevel,
target: LoggingTarget::Stderr {
format: self.logformat,
},
}
.initialize();
if let Err(e) = res {
#[expect(clippy::print_stderr)]
for e in e.chain() {
eprintln!("{e}");
}
std::process::exit(1);
}
}
pub fn make_runtime(&self) -> tokio::runtime::Runtime {
let mut rt = tokio::runtime::Builder::new_multi_thread();
rt.enable_all();
if let Some(threads) = self.runtime_threads {
rt.worker_threads(threads.into());
}
if let Some(threads) = self.blocking_threads {
rt.max_blocking_threads(threads.into());
}
#[expect(clippy::unwrap_used)]
let rt = rt.build().unwrap();
return rt;
}
}

View File

@@ -1,10 +1,11 @@
use clap::Parser;
use toolbox::logging::{LogCliVQ, LoggingFormat, LoggingInitializer, LoggingTarget};
use toolbox::logging::LogCliVQ;
use tracing::error;
use crate::cmd::Command;
use crate::{cmd::Command, config::WebpageConfig};
mod cmd;
mod config;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None, styles=toolbox::cli::clap_styles())]
@@ -20,36 +21,19 @@ struct Cli {
command: Command,
}
#[derive(Debug)]
pub struct CmdContext {}
pub struct CmdContext {
config: WebpageConfig,
}
#[tokio::main]
async fn main() {
fn main() {
let cli = Cli::parse();
let ctx = CmdContext {
config: WebpageConfig::load(),
};
{
let res = LoggingInitializer {
app_name: "webpage",
loki: None,
preset: cli.vq.into_preset(),
target: LoggingTarget::Stderr {
format: LoggingFormat::Ansi,
},
}
.initialize();
if let Err(e) = res {
#[expect(clippy::print_stderr)]
for e in e.chain() {
eprintln!("{e}");
}
std::process::exit(1);
}
}
let ctx = CmdContext {};
let res = cli.command.run(ctx).await;
let rt = ctx.config.make_runtime();
rt.block_on(ctx.config.init_logging());
let res = rt.block_on(cli.command.run(ctx));
if let Err(e) = res {
for e in e.chain() {