exercises

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

config.rs (3689B)


      1 //! Configuration management for the orders service
      2 //!
      3 //! This module handles loading and parsing configuration from multiple sources:
      4 //! 1. config.toml file (base configuration)
      5 //! 2. Environment variables prefixed with `ORDERS_` (overrides)
      6 //!
      7 //! # Environment Variables
      8 //! - `ORDERS_SERVER_PORT` - Override server port
      9 //! - `ORDERS_DATABASE_URL` - Override database connection string
     10 //! - `ORDERS_DATABASE_MAX_CONNECTIONS` - Override max database connections
     11 //!
     12 //! # Example config.toml
     13 //! ```toml
     14 //! [server]
     15 //! port = 3003
     16 //!
     17 //! [database]
     18 //! url = "postgres://user:pass@localhost:5432/dbname"
     19 //! max_connections = 10
     20 //! ```
     21 
     22 use anyhow::Result;
     23 use serde::Deserialize;
     24 
     25 /// Root configuration structure
     26 ///
     27 /// Loaded from config.toml and can be overridden with environment variables.
     28 #[derive(Debug, Deserialize, Clone)]
     29 pub struct Config {
     30     /// Server configuration (port)
     31     pub server: ServerConfig,
     32 
     33     /// Database connection configuration
     34     pub database: DatabaseConfig,
     35 
     36     /// Microservices configuration
     37     pub services: ServicesConfig,
     38 
     39     /// HTTP client configuration
     40     pub http_client: HttpClientConfig,
     41 }
     42 
     43 /// Server configuration
     44 #[derive(Debug, Deserialize, Clone)]
     45 pub struct ServerConfig {
     46     /// Port to bind the HTTP server to (default: 3003)
     47     pub port: u16,
     48 }
     49 
     50 /// Database connection configuration
     51 #[derive(Debug, Deserialize, Clone)]
     52 pub struct DatabaseConfig {
     53     /// PostgreSQL connection string
     54     /// Format: postgres://user:password@host:port/database
     55     pub url: String,
     56 
     57     /// Maximum number of connections in the connection pool
     58     /// Recommended: 5-20 for most applications
     59     pub max_connections: u32,
     60 }
     61 
     62 /// Microservices configuration
     63 #[derive(Debug, Deserialize, Clone)]
     64 pub struct ServicesConfig {
     65     /// Products service host
     66     pub products_host: String,
     67     /// Products service port
     68     pub products_port: u16,
     69     /// Inventory service host
     70     pub inventory_host: String,
     71     /// Inventory service port
     72     pub inventory_port: u16,
     73 }
     74 
     75 impl ServicesConfig {
     76     /// Get the full products service URL
     77     pub fn products_service_url(&self) -> String {
     78         format!("http://{}:{}", self.products_host, self.products_port)
     79     }
     80 
     81     /// Get the full inventory service URL
     82     pub fn inventory_service_url(&self) -> String {
     83         format!("http://{}:{}", self.inventory_host, self.inventory_port)
     84     }
     85 }
     86 
     87 /// HTTP client configuration
     88 #[derive(Debug, Deserialize, Clone)]
     89 pub struct HttpClientConfig {
     90     /// Request timeout in seconds
     91     pub timeout_secs: u64,
     92 }
     93 
     94 impl Config {
     95     /// Load configuration from config.toml and environment variables
     96     ///
     97     /// Configuration is loaded in this order (later sources override earlier ones):
     98     /// 1. config.toml in the current directory
     99     /// 2. Environment variables with `ORDERS_` prefix
    100     ///
    101     /// # Example Environment Override
    102     /// ```bash
    103     /// export ORDERS_SERVER_PORT=8080
    104     /// export ORDERS_DATABASE_URL=postgres://localhost/mydb
    105     /// ```
    106     ///
    107     /// # Errors
    108     /// Returns an error if:
    109     /// - config.toml is not found or invalid
    110     /// - Required fields are missing
    111     /// - Environment variable format is invalid
    112     pub fn load() -> Result<Self> {
    113         let config = config::Config::builder()
    114             // Load from config.toml file
    115             .add_source(config::File::with_name("config"))
    116             // Override with environment variables (e.g., ORDERS_SERVER_PORT)
    117             .add_source(config::Environment::with_prefix("ORDERS"))
    118             .build()?;
    119 
    120         // Deserialize into our Config struct
    121         let config: Config = config.try_deserialize()?;
    122         Ok(config)
    123     }
    124 }