package database import ( "fmt" "os" "time" "github.com/prometheus/client_golang/prometheus" ) // Config represents the database configuration structure type Config struct { // MySQL configuration (use this OR Postgres, not both) MySQL *MySQLConfig `yaml:"mysql,omitempty"` // Postgres configuration (use this OR MySQL, not both) Postgres *PostgresConfig `yaml:"postgres,omitempty"` // Legacy flat PostgreSQL format (deprecated, for backward compatibility only) // If neither MySQL nor Postgres is set, these fields will be used for PostgreSQL User string `yaml:"user,omitempty"` Pass string `yaml:"pass,omitempty"` Host string `yaml:"host,omitempty"` Port uint16 `yaml:"port,omitempty"` Name string `yaml:"name,omitempty"` SSLMode string `yaml:"sslmode,omitempty"` } // MySQLConfig represents the MySQL database configuration type MySQLConfig struct { DSN string `yaml:"dsn" default:"" flag:"dsn" usage:"Database DSN"` User string `yaml:"user" default:"" flag:"user"` Pass string `yaml:"pass" default:"" flag:"pass"` DBName string `yaml:"name,omitempty"` // Optional database name override } // PostgresConfig represents the PostgreSQL database configuration type PostgresConfig struct { User string `yaml:"user"` Pass string `yaml:"pass"` Host string `yaml:"host"` Port uint16 `yaml:"port"` Name string `yaml:"name"` SSLMode string `yaml:"sslmode"` } // DBConfig is a legacy alias for MySQLConfig type DBConfig = MySQLConfig // Validate ensures the configuration is valid and unambiguous func (c *Config) Validate() error { hasMySQL := c.MySQL != nil hasPostgres := c.Postgres != nil hasLegacy := c.User != "" || c.Host != "" || c.Port != 0 || c.Name != "" count := 0 if hasMySQL { count++ } if hasPostgres { count++ } if hasLegacy { count++ } if count == 0 { return fmt.Errorf("no database configuration provided") } if count > 1 { return fmt.Errorf("multiple database configurations provided (only one allowed)") } return nil } // ConfigOptions allows customization of database opening behavior type ConfigOptions struct { // ConfigFiles is a list of config file paths to search for database configuration ConfigFiles []string // EnablePoolMonitoring enables connection pool metrics collection EnablePoolMonitoring bool // PrometheusRegisterer for metrics collection. If nil, no metrics are collected. PrometheusRegisterer prometheus.Registerer // Connection pool settings MaxOpenConns int MaxIdleConns int ConnMaxLifetime time.Duration } // getConfigFiles returns the list of config files to search for database configuration. // If DATABASE_CONFIG_FILE environment variable is set, it returns that single file. // Otherwise, it returns the default paths. func getConfigFiles() []string { if configFile := os.Getenv("DATABASE_CONFIG_FILE"); configFile != "" { return []string{configFile} } return []string{"database.yaml", "/vault/secrets/database.yaml"} } // DefaultConfigOptions returns the standard configuration options used by API package func DefaultConfigOptions() ConfigOptions { return ConfigOptions{ ConfigFiles: getConfigFiles(), EnablePoolMonitoring: true, PrometheusRegisterer: prometheus.DefaultRegisterer, MaxOpenConns: 25, MaxIdleConns: 10, ConnMaxLifetime: 3 * time.Minute, } } // MonitorConfigOptions returns configuration options optimized for Monitor package func MonitorConfigOptions() ConfigOptions { return ConfigOptions{ ConfigFiles: getConfigFiles(), EnablePoolMonitoring: false, // Monitor doesn't need metrics PrometheusRegisterer: nil, // No Prometheus dependency MaxOpenConns: 10, MaxIdleConns: 5, ConnMaxLifetime: 3 * time.Minute, } }