mecha10_core/context/
config.rs1use super::{Context, InfrastructureConfig};
4use crate::error::{Mecha10Error, Result};
5use anyhow::Context as _;
6
7impl Context {
8 pub(super) fn load_infrastructure_config() -> Result<InfrastructureConfig> {
17 use crate::config::load_config;
18 use std::env;
19 use std::path::PathBuf;
20
21 if let Ok(redis_url) = Self::try_load_redis_from_mecha10_json() {
23 return Ok(InfrastructureConfig {
24 redis: crate::context::infra_config::RedisConfig {
25 url: redis_url,
26 max_connections: 10,
27 connection_timeout_ms: 5000,
28 },
29 control_plane_redis: None,
30 bridge: None,
31 postgres: None,
32 mlflow: None,
33 minio: None,
34 });
35 }
36
37 if let Ok(redis_url) = env::var("MECHA10_REDIS_URL").or_else(|_| env::var("REDIS_URL")) {
40 return Ok(InfrastructureConfig {
41 redis: crate::context::infra_config::RedisConfig {
42 url: redis_url,
43 max_connections: 10,
44 connection_timeout_ms: 5000,
45 },
46 control_plane_redis: None,
47 bridge: None,
48 postgres: None,
49 mlflow: None,
50 minio: None,
51 });
52 }
53
54 let environment = env::var("MECHA10_ENVIRONMENT").unwrap_or_else(|_| "development".to_string());
56
57 let config_filename = format!("infrastructure.{}.yaml", environment);
58
59 let paths_to_try = vec![
64 PathBuf::from(format!("config/{}", config_filename)),
65 PathBuf::from(format!("../../config/{}", config_filename)),
66 PathBuf::from(format!("../../../../config/{}", config_filename)),
67 ];
68
69 for path in &paths_to_try {
70 if path.exists() {
71 return load_config(path)
72 .with_context(|| {
73 format!(
74 "Failed to load infrastructure config for environment '{}' from '{}'",
75 environment,
76 path.display()
77 )
78 })
79 .map_err(|e| Mecha10Error::Configuration(format!("{:#}", e)));
80 }
81 }
82
83 Err(Mecha10Error::Configuration(format!(
85 "Failed to load infrastructure config for environment '{}'. \
86 Tried paths: {}. \
87 Make sure the file exists, set MECHA10_REDIS_URL environment variable, \
88 or configure redis.url in mecha10.json.",
89 environment,
90 paths_to_try
91 .iter()
92 .map(|p| p.display().to_string())
93 .collect::<Vec<_>>()
94 .join(", ")
95 )))
96 }
97
98 fn try_load_redis_from_mecha10_json() -> Result<String> {
102 use std::path::PathBuf;
103
104 let paths_to_try = vec![
106 PathBuf::from("mecha10.json"),
107 PathBuf::from("../mecha10.json"),
108 PathBuf::from("../../mecha10.json"),
109 ];
110
111 for path in &paths_to_try {
112 if !path.exists() {
113 continue;
114 }
115
116 let content = std::fs::read_to_string(path)
118 .map_err(|e| Mecha10Error::Configuration(format!("Failed to read {}: {}", path.display(), e)))?;
119
120 let json: serde_json::Value = serde_json::from_str(&content)
121 .map_err(|e| Mecha10Error::Configuration(format!("Failed to parse {}: {}", path.display(), e)))?;
122
123 if let Some(redis_url) = json.get("redis").and_then(|r| r.get("url")).and_then(|u| u.as_str()) {
125 return Ok(redis_url.to_string());
126 }
127 }
128
129 Err(Mecha10Error::Configuration(
130 "No mecha10.json found with redis.url configuration".to_string(),
131 ))
132 }
133
134 pub(super) fn get_redis_url_from_config(config: &InfrastructureConfig) -> Result<String> {
136 if let Ok(url) = std::env::var("MECHA10_REDIS_URL") {
138 return Ok(url);
139 }
140 if let Ok(url) = std::env::var("REDIS_URL") {
141 return Ok(url);
142 }
143
144 Ok(config.redis.url.clone())
146 }
147
148 pub fn get_redis_url() -> Result<String> {
150 let config = Self::load_infrastructure_config()?;
151 Self::get_redis_url_from_config(&config)
152 }
153
154 pub fn get_control_plane_redis_url() -> Result<Option<String>> {
156 let config = Self::load_infrastructure_config()?;
157 Ok(config.control_plane_redis.map(|c| c.url))
158 }
159}