smith_config/app.rs
1use anyhow::{Context, Result};
2use once_cell::sync::OnceCell;
3
4use crate::Config;
5
6/// Global, lazily-initialized configuration cache.
7///
8/// Loads configuration once from the environment (including overrides) and
9/// shares the resulting `Config` across all callers. This avoids repeated
10/// env/file parsing throughout the process and centralizes configuration
11/// injection at startup.
12static GLOBAL_CONFIG: OnceCell<Config> = OnceCell::new();
13
14/// Load configuration from the environment and cache it for subsequent calls.
15///
16/// The first caller populates the cache; later callers get the same instance.
17pub fn load_from_env() -> Result<&'static Config> {
18 GLOBAL_CONFIG.get_or_try_init(|| {
19 let mut config = Config::from_env().context("Failed to load configuration")?;
20 if let Err(err) = config.apply_env_overrides() {
21 tracing::warn!(error = %err, "Failed to apply environment overrides; continuing with base config");
22 }
23 Ok(config)
24 })
25}
26
27/// Get the cached configuration, assuming it has been loaded via `load_from_env`.
28/// Panics if called before initialization.
29pub fn get() -> &'static Config {
30 GLOBAL_CONFIG
31 .get()
32 .expect("Config not initialized; call load_from_env first")
33}