package config import ( "fmt" "os" "strconv" "github.com/rs/zerolog" ) // Environment variable names const ( EnvLogLevel = "LOG_LEVEL" EnvRootPath = "ROOT_PATH" EnvNumWorkers = "NUM_OF_WORKERS" EnvWorkerBatchSize = "WORKER_BATCH_SIZE" EnvMaxResponseSize = "MAX_RESPONSE_SIZE" EnvResponseTimeout = "RESPONSE_TIMEOUT" ) // Config holds the application configuration loaded from environment variables type Config struct { LogLevel zerolog.Level // Logging level (debug, info, warn, error) RootPath string // Root path for the application MaxResponseSize int // Maximum size of response in bytes NumOfWorkers int // Number of concurrent workers ResponseTimeout int // Timeout for responses in seconds WorkerBatchSize int // Batch size for worker processing } // String returns a string representation of the configuration func (c *Config) String() string { return fmt.Sprintf( "Config{LogLevel: %s, RootPath: %s, MaxResponseSize: %d, NumWorkers: %d, ResponseTimeout: %d, WorkerBatchSize: %d}", c.LogLevel, c.RootPath, c.MaxResponseSize, c.NumOfWorkers, c.ResponseTimeout, c.WorkerBatchSize, ) } var CONFIG Config // parsePositiveInt parses and validates positive integer values func parsePositiveInt(param, value string) (int, error) { val, err := strconv.Atoi(value) if err != nil { return 0, &ValidationError{ Param: param, Value: value, Reason: "must be a valid integer", } } if val <= 0 { return 0, &ValidationError{ Param: param, Value: value, Reason: "must be positive", } } return val, nil } // GetConfig loads and validates configuration from environment variables func GetConfig() *Config { config := &Config{} // Map of environment variables to their parsing functions parsers := map[string]func(string) error{ EnvLogLevel: func(v string) error { level, err := zerolog.ParseLevel(v) if err != nil { return &ValidationError{ Param: EnvLogLevel, Value: v, Reason: "must be one of: debug, info, warn, error", } } config.LogLevel = level return nil }, EnvRootPath: func(v string) error { if _, err := os.Stat(v); err != nil { return &ConfigError{ Param: EnvRootPath, Err: err, } } config.RootPath = v return nil }, EnvNumWorkers: func(v string) error { val, err := parsePositiveInt(EnvNumWorkers, v) if err != nil { return err } config.NumOfWorkers = val return nil }, EnvWorkerBatchSize: func(v string) error { val, err := parsePositiveInt(EnvWorkerBatchSize, v) if err != nil { return err } config.WorkerBatchSize = val return nil }, EnvMaxResponseSize: func(v string) error { val, err := parsePositiveInt(EnvMaxResponseSize, v) if err != nil { return err } config.MaxResponseSize = val return nil }, EnvResponseTimeout: func(v string) error { val, err := parsePositiveInt(EnvResponseTimeout, v) if err != nil { return err } config.ResponseTimeout = val return nil }, } // Process each environment variable for envVar, parser := range parsers { value, ok := os.LookupEnv(envVar) if !ok { fmt.Fprintf(os.Stderr, "Missing required environment variable: %s\n", envVar) os.Exit(1) } if err := parser(value); err != nil { fmt.Fprintf(os.Stderr, "Configuration error: %v\n", err) os.Exit(1) } } return config }