exercises

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

config.rs (2828B)


      1 use anyhow::Result;
      2 use serde::Deserialize;
      3 use std::path::Path;
      4 
      5 /// Application configuration loaded from config.toml
      6 #[derive(Debug, Clone, Deserialize)]
      7 pub struct Config {
      8     pub server: ServerConfig,
      9     pub database: DatabaseConfig,
     10     pub services: ServicesConfig,
     11     pub http_client: HttpClientConfig,
     12     pub session: SessionConfig,
     13 }
     14 
     15 /// Server configuration
     16 #[derive(Debug, Clone, Deserialize)]
     17 pub struct ServerConfig {
     18     pub port: u16,
     19     pub static_dir: String,
     20 }
     21 
     22 /// Database configuration
     23 #[derive(Debug, Clone, Deserialize)]
     24 pub struct DatabaseConfig {
     25     pub url: String,
     26     pub max_connections: u32,
     27 }
     28 
     29 /// Microservices configuration
     30 #[derive(Debug, Clone, Deserialize)]
     31 pub struct ServicesConfig {
     32     pub products_host: String,
     33     pub products_port: u16,
     34     pub inventory_host: String,
     35     pub inventory_port: u16,
     36     pub orders_host: String,
     37     pub orders_port: u16,
     38     pub checkout_host: String,
     39     pub checkout_port: u16,
     40     pub inventory_service_url: String,
     41     pub orders_service_url: String,
     42 }
     43 
     44 impl ServicesConfig {
     45     /// Get the full products service URL
     46     pub fn products_service_url(&self) -> String {
     47         format!("http://{}:{}", self.products_host, self.products_port)
     48     }
     49 
     50     /// Get the full inventory service URL
     51     pub fn inventory_service_url_computed(&self) -> String {
     52         format!("http://{}:{}", self.inventory_host, self.inventory_port)
     53     }
     54 
     55     /// Get the full orders service URL
     56     pub fn orders_service_url_computed(&self) -> String {
     57         format!("http://{}:{}", self.orders_host, self.orders_port)
     58     }
     59 
     60     /// Get the full checkout service URL
     61     pub fn checkout_service_url(&self) -> String {
     62         format!("http://{}:{}", self.checkout_host, self.checkout_port)
     63     }
     64 }
     65 
     66 /// HTTP client configuration
     67 #[derive(Debug, Clone, Deserialize)]
     68 pub struct HttpClientConfig {
     69     pub timeout_secs: u64,
     70 }
     71 
     72 /// Session configuration
     73 #[derive(Debug, Clone, Deserialize)]
     74 pub struct SessionConfig {
     75     pub expiration_days: i64,
     76 }
     77 
     78 impl Config {
     79     /// Load configuration from a TOML file with environment variable overrides
     80     pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
     81         let config = config::Config::builder()
     82             .add_source(config::File::from(path.as_ref()))
     83             // Allow environment variables to override config file values
     84             // Using __ as separator for nested fields: APP_SERVICES__PRODUCTS_HOST
     85             .add_source(
     86                 config::Environment::with_prefix("APP")
     87                     .separator("__")
     88                     .try_parsing(true)
     89             )
     90             .build()?;
     91 
     92         Ok(config.try_deserialize()?)
     93     }
     94 
     95     /// Load configuration from default location (./config.toml)
     96     pub fn load() -> Result<Self> {
     97         Self::from_file("config.toml")
     98     }
     99 }