Configure server though env
All checks were successful
CI / Typos (push) Successful in 21s
CI / Build and test (push) Successful in 2m33s
CI / Clippy (push) Successful in 3m12s
Docker / build-and-push (push) Successful in 5m35s
CI / Build and test (all features) (push) Successful in 7m1s

This commit is contained in:
2026-03-26 20:40:51 -07:00
parent 256af68382
commit 5807733e62
10 changed files with 579 additions and 66 deletions

View File

@@ -0,0 +1,109 @@
use serde::Deserialize;
use std::{num::NonZeroUsize, path::PathBuf};
use tracing::info;
use crate::config::{
env::load_env,
logging::{LoggingFormat, LoggingInitializer, LoggingPreset, LoggingTarget, LokiConfig},
};
/// Note that the field of this struct are not capitalized.
/// Envy is case-insensitive, and expects Rust fields to be snake_case.
#[derive(Debug, Deserialize, Clone)]
pub struct PileServerConfig {
#[serde(flatten)]
pub loki: Option<LokiConfig>,
/// The logging level to run with
#[serde(default)]
pub loglevel: LoggingPreset,
#[serde(default)]
pub logformat: LoggingFormat,
/// How many worker threads to use
pub threads: Option<NonZeroUsize>,
/// IP and port to bind to
/// Should look like `127.0.0.1:3030`
pub server_addr: String,
pub api_token: Option<String>,
pub workdir_root: PathBuf,
}
impl Default for PileServerConfig {
fn default() -> Self {
Self {
loki: None,
loglevel: LoggingPreset::Debug,
logformat: LoggingFormat::Ansi,
threads: None,
server_addr: "0.0.0.0:3000".into(),
api_token: None,
workdir_root: "./.pile".into(),
}
}
}
impl PileServerConfig {
pub fn load(with_env: bool, cli_log_level: LoggingPreset) -> Self {
let config = match with_env {
false => Self::default(),
true => {
let env = match load_env::<Self>() {
Ok(x) => x,
#[expect(clippy::print_stdout)]
Err(err) => {
println!("Error while loading .env: {err}");
std::process::exit(1);
}
};
env.get_config().clone()
}
};
{
let res = LoggingInitializer {
app_name: "pile-server",
loki: config.loki.clone(),
preset: if with_env {
config.loglevel
} else {
cli_log_level
},
target: LoggingTarget::Stderr {
format: config.logformat,
},
}
.initialize();
if let Err(e) = res {
#[expect(clippy::print_stderr)]
for e in e.chain() {
eprintln!("{e}");
}
std::process::exit(1);
}
}
info!(message = "Config loaded", ?config);
return config;
}
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.threads {
rt.worker_threads(threads.into());
}
#[expect(clippy::unwrap_used)]
let rt = rt.build().unwrap();
return rt;
}
}