backbone_bucket/config/
app_config.rs1use serde::Deserialize;
6use std::path::Path;
7
8#[derive(Debug, Clone, Deserialize)]
10pub struct ModuleConfig {
11 pub server: ServerConfig,
12 pub database: DatabaseConfig,
13 pub module: ModuleSettings,
14 #[serde(default)]
15 pub features: FeatureFlags,
16 #[serde(default)]
17 pub logging: LoggingConfig,
18}
19
20#[derive(Debug, Clone, Deserialize)]
21pub struct ServerConfig {
22 pub host: String,
23 pub port: u16,
24 #[serde(default = "default_grpc_port")]
25 pub grpc_port: u16,
26}
27
28fn default_grpc_port() -> u16 {
29 50051
30}
31
32#[derive(Debug, Clone, Deserialize)]
33pub struct DatabaseConfig {
34 pub url: String,
35 #[serde(default = "default_max_connections")]
36 pub max_connections: u32,
37 #[serde(default = "default_min_connections")]
38 pub min_connections: u32,
39 #[serde(default = "default_connect_timeout")]
40 pub connect_timeout: u64,
41 #[serde(default = "default_idle_timeout")]
42 pub idle_timeout: u64,
43}
44
45fn default_max_connections() -> u32 {
46 20
47}
48fn default_min_connections() -> u32 {
49 5
50}
51fn default_connect_timeout() -> u64 {
52 30
53}
54fn default_idle_timeout() -> u64 {
55 600
56}
57
58#[derive(Debug, Clone, Deserialize)]
59pub struct ModuleSettings {
60 pub name: String,
61 #[serde(default = "default_enabled")]
62 pub enabled: bool,
63}
64
65fn default_enabled() -> bool {
66 true
67}
68
69#[derive(Debug, Clone, Deserialize, Default)]
70pub struct FeatureFlags {
71 #[serde(default)]
72 pub soft_delete: bool,
73 #[serde(default)]
74 pub state_machines: bool,
75 #[serde(default)]
76 pub workflows: bool,
77}
78
79#[derive(Debug, Clone, Deserialize)]
80pub struct LoggingConfig {
81 #[serde(default = "default_log_level")]
82 pub level: String,
83 #[serde(default = "default_log_format")]
84 pub format: String,
85}
86
87fn default_log_level() -> String {
88 "info".to_string()
89}
90fn default_log_format() -> String {
91 "json".to_string()
92}
93
94impl Default for LoggingConfig {
95 fn default() -> Self {
96 Self {
97 level: default_log_level(),
98 format: default_log_format(),
99 }
100 }
101}
102
103impl ModuleConfig {
104 pub fn from_file<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> {
106 let content = std::fs::read_to_string(path)?;
107 let config: ModuleConfig = serde_yaml::from_str(&content)?;
108 Ok(config)
109 }
110
111 pub fn load(env: Option<&str>) -> anyhow::Result<Self> {
113 let base_path = "config/application.yml";
114 let mut config = Self::from_file(base_path)?;
115
116 if let Some(environment) = env {
117 let env_path = format!("config/application-{}.yml", environment);
118 if Path::new(&env_path).exists() {
119 let env_content = std::fs::read_to_string(&env_path)?;
120 let env_config: serde_yaml::Value = serde_yaml::from_str(&env_content)?;
121 if let Ok(merged) = serde_yaml::from_value(env_config) {
124 config = merged;
125 }
126 }
127 }
128
129 Ok(config)
130 }
131}