Skip to main content

road_runner_common/
config.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
4pub struct ServiceConfig {
5    pub service_name: String,
6    pub log_level: String,  // "info" | "debug" vb
7    pub log_format: String, // "json" | "pretty"
8    pub max_page_size: u32,
9}
10
11impl Default for ServiceConfig {
12    fn default() -> Self {
13        Self {
14            service_name: "my-service".to_string(),
15            log_level: "info".to_string(),
16            log_format: "json".to_string(),
17            max_page_size: 100,
18        }
19    }
20}
21
22impl ServiceConfig {
23    pub fn from_env_fallback() -> Self {
24        let mut cfg = Self::default();
25
26        if let Ok(v) = std::env::var("SERVICE_NAME") {
27            cfg.service_name = v;
28        }
29        if let Ok(v) = std::env::var("LOG_LEVEL") {
30            cfg.log_level = v;
31        }
32        if let Ok(v) = std::env::var("LOG_FORMAT") {
33            cfg.log_format = v;
34        }
35        if let Ok(v) = std::env::var("MAX_PAGE_SIZE") {
36            if let Ok(n) = v.parse::<u32>() {
37                cfg.max_page_size = n.max(1);
38            }
39        }
40        cfg
41    }
42
43    #[cfg(feature = "config")]
44    pub fn load() -> anyhow::Result<Self> {
45        let _ = dotenvy::dotenv();
46
47        let config_file = std::env::var("CONFIG_FILE").ok();
48
49        let mut builder = config::Config::builder();
50
51        if let Some(path) = config_file {
52            builder = builder.add_source(config::File::with_name(&path).required(false));
53        }
54
55        builder = builder.add_source(config::Environment::default());
56
57        let cfg = builder.build()?;
58        Ok(cfg.try_deserialize()?)
59    }
60}