exercises

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

config.rs (2688B)


      1 //! Configuration management for the products 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 `PRODUCTS_` (overrides)
      6 //!
      7 //! # Environment Variables
      8 //! - `PRODUCTS_SERVER_PORT` - Override server port
      9 //! - `PRODUCTS_DATABASE_URL` - Override database connection string
     10 //! - `PRODUCTS_DATABASE_MAX_CONNECTIONS` - Override max database connections
     11 //!
     12 //! # Example config.toml
     13 //! ```toml
     14 //! [server]
     15 //! port = 3001
     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 
     37 /// Server configuration
     38 #[derive(Debug, Deserialize, Clone)]
     39 pub struct ServerConfig {
     40     /// Port to bind the HTTP server to (default: 3001)
     41     pub port: u16,
     42 }
     43 
     44 /// Database connection configuration
     45 #[derive(Debug, Deserialize, Clone)]
     46 pub struct DatabaseConfig {
     47     /// PostgreSQL connection string
     48     /// Format: postgres://user:password@host:port/database
     49     pub url: String,
     50 
     51     /// Maximum number of connections in the connection pool
     52     /// Recommended: 5-20 for most applications
     53     pub max_connections: u32,
     54 }
     55 
     56 impl Config {
     57     /// Load configuration from config.toml and environment variables
     58     ///
     59     /// Configuration is loaded in this order (later sources override earlier ones):
     60     /// 1. config.toml in the current directory
     61     /// 2. Environment variables with `PRODUCTS_` prefix
     62     ///
     63     /// # Example Environment Override
     64     /// ```bash
     65     /// export PRODUCTS_SERVER_PORT=8080
     66     /// export PRODUCTS_DATABASE_URL=postgres://localhost/mydb
     67     /// ```
     68     ///
     69     /// # Errors
     70     /// Returns an error if:
     71     /// - config.toml is not found or invalid
     72     /// - Required fields are missing
     73     /// - Environment variable format is invalid
     74     pub fn load() -> Result<Self> {
     75         let config = config::Config::builder()
     76             // Load from config.toml file
     77             .add_source(config::File::with_name("config"))
     78             // Override with environment variables (e.g., PRODUCTS_SERVER_PORT)
     79             .add_source(config::Environment::with_prefix("PRODUCTS"))
     80             .build()?;
     81 
     82         // Deserialize into our Config struct
     83         let config: Config = config.try_deserialize()?;
     84         Ok(config)
     85     }
     86 }