package config import ( "fmt" "os" "gopkg.in/yaml.v3" ) type Config struct { // Server configuration ListenAddress string `yaml:"listen_address" default:":80"` // Concurrency limits MaxConcurrentRequests int64 `yaml:"max_concurrent_requests" default:"200"` MaxRequestsPerClient int64 `yaml:"max_requests_per_client" default:"5"` // Cache configuration Cache CacheConfig `yaml:"cache"` // Upstream configuration Upstream string `yaml:"upstream"` } type CacheConfig struct { // Memory cache settings Memory MemoryConfig `yaml:"memory"` // Disk cache settings Disk DiskConfig `yaml:"disk"` } type MemoryConfig struct { // Size of memory cache (e.g., "512MB", "1GB") Size string `yaml:"size" default:"0"` // Garbage collection algorithm: lru, lfu, fifo, largest, smallest, hybrid GCAlgorithm string `yaml:"gc_algorithm" default:"lru"` } type DiskConfig struct { // Size of disk cache (e.g., "10GB", "50GB") Size string `yaml:"size" default:"0"` // Path to disk cache directory Path string `yaml:"path" default:""` // Garbage collection algorithm: lru, lfu, fifo, largest, smallest, hybrid GCAlgorithm string `yaml:"gc_algorithm" default:"lru"` } // LoadConfig loads configuration from a YAML file func LoadConfig(configPath string) (*Config, error) { if configPath == "" { configPath = "config.yaml" } data, err := os.ReadFile(configPath) if err != nil { return nil, fmt.Errorf("failed to read config file %s: %w", configPath, err) } var config Config if err := yaml.Unmarshal(data, &config); err != nil { return nil, fmt.Errorf("failed to parse config file %s: %w", configPath, err) } // Set defaults for empty values if config.ListenAddress == "" { config.ListenAddress = ":80" } if config.MaxConcurrentRequests == 0 { config.MaxConcurrentRequests = 50 } if config.MaxRequestsPerClient == 0 { config.MaxRequestsPerClient = 3 } if config.Cache.Memory.Size == "" { config.Cache.Memory.Size = "0" } if config.Cache.Memory.GCAlgorithm == "" { config.Cache.Memory.GCAlgorithm = "lru" } if config.Cache.Disk.Size == "" { config.Cache.Disk.Size = "0" } if config.Cache.Disk.GCAlgorithm == "" { config.Cache.Disk.GCAlgorithm = "lru" } return &config, nil } // SaveDefaultConfig creates a default configuration file func SaveDefaultConfig(configPath string) error { if configPath == "" { configPath = "config.yaml" } defaultConfig := Config{ ListenAddress: ":80", MaxConcurrentRequests: 50, // Reduced for home user (less concurrent load) MaxRequestsPerClient: 3, // Reduced for home user (more conservative per client) Cache: CacheConfig{ Memory: MemoryConfig{ Size: "1GB", // Recommended for systems that can spare 1GB RAM for caching GCAlgorithm: "lru", }, Disk: DiskConfig{ Size: "1TB", // Large HDD cache for home user Path: "./disk", GCAlgorithm: "lru", // Better for gaming patterns (keeps recently played games) }, }, Upstream: "", } data, err := yaml.Marshal(&defaultConfig) if err != nil { return fmt.Errorf("failed to marshal default config: %w", err) } if err := os.WriteFile(configPath, data, 0644); err != nil { return fmt.Errorf("failed to write default config file: %w", err) } return nil }