Files
pgsql-broker/pkg/broker/config/config.go

181 lines
5.1 KiB
Go

package config
import (
"fmt"
"time"
"github.com/spf13/viper"
"git.warky.dev/wdevs/pgsql-broker/pkg/broker/adapter"
)
// Config holds all broker configuration
type Config struct {
Databases []DatabaseConfig `mapstructure:"databases"`
Broker BrokerConfig `mapstructure:"broker"`
Logging LoggingConfig `mapstructure:"logging"`
}
// DatabaseConfig holds database connection settings
type DatabaseConfig struct {
Name string `mapstructure:"name"`
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Database string `mapstructure:"database"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
SSLMode string `mapstructure:"sslmode"`
MaxOpenConns int `mapstructure:"max_open_conns"`
MaxIdleConns int `mapstructure:"max_idle_conns"`
ConnMaxLifetime time.Duration `mapstructure:"conn_max_lifetime"`
ConnMaxIdleTime time.Duration `mapstructure:"conn_max_idle_time"`
QueueCount int `mapstructure:"queue_count"`
}
// BrokerConfig holds broker-specific settings
type BrokerConfig struct {
Name string `mapstructure:"name"`
FetchQueryQueSize int `mapstructure:"fetch_query_que_size"`
QueueTimerSec int `mapstructure:"queue_timer_sec"`
QueueBufferSize int `mapstructure:"queue_buffer_size"`
WorkerIdleTimeoutSec int `mapstructure:"worker_idle_timeout_sec"`
NotifyRetrySeconds time.Duration `mapstructure:"notify_retry_seconds"`
EnableDebug bool `mapstructure:"enable_debug"`
}
// LoggingConfig holds logging settings
type LoggingConfig struct {
Level string `mapstructure:"level"`
Format string `mapstructure:"format"` // json or text
}
// LoadConfig loads configuration from file and environment variables
func LoadConfig(configPath string) (*Config, error) {
v := viper.New()
// Set defaults
setDefaults(v)
// Config file settings
if configPath != "" {
v.SetConfigFile(configPath)
} else {
v.SetConfigName("broker")
v.SetConfigType("yaml")
v.AddConfigPath(".")
v.AddConfigPath("/etc/pgsql-broker/")
v.AddConfigPath("$HOME/.pgsql-broker/")
}
// Read from environment variables
v.SetEnvPrefix("BROKER")
v.AutomaticEnv()
// Read config file
if err := v.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
return nil, fmt.Errorf("failed to read config file: %w", err)
}
}
var config Config
if err := v.Unmarshal(&config); err != nil {
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
}
// Validate configuration
if err := validateConfig(&config); err != nil {
return nil, err
}
// Apply defaults to databases
applyDatabaseDefaults(&config)
return &config, nil
}
// setDefaults sets default configuration values
func setDefaults(v *viper.Viper) {
// Broker defaults
v.SetDefault("broker.name", "pgsql-broker")
v.SetDefault("broker.fetch_query_que_size", 100)
v.SetDefault("broker.queue_timer_sec", 10)
v.SetDefault("broker.queue_buffer_size", 50)
v.SetDefault("broker.worker_idle_timeout_sec", 10)
v.SetDefault("broker.notify_retry_seconds", 30*time.Second)
v.SetDefault("broker.enable_debug", false)
// Logging defaults
v.SetDefault("logging.level", "info")
v.SetDefault("logging.format", "json")
}
// validateConfig validates the configuration
func validateConfig(config *Config) error {
if len(config.Databases) == 0 {
return fmt.Errorf("at least one database must be configured")
}
// Validate each database configuration
for i, db := range config.Databases {
if db.Name == "" {
return fmt.Errorf("database[%d]: name is required", i)
}
if db.Host == "" {
return fmt.Errorf("database[%d] (%s): host is required", i, db.Name)
}
if db.Database == "" {
return fmt.Errorf("database[%d] (%s): database name is required", i, db.Name)
}
if db.User == "" {
return fmt.Errorf("database[%d] (%s): user is required", i, db.Name)
}
}
return nil
}
// applyDatabaseDefaults applies default values to database configurations
func applyDatabaseDefaults(config *Config) {
for i := range config.Databases {
db := &config.Databases[i]
if db.Port == 0 {
db.Port = 5432
}
if db.SSLMode == "" {
db.SSLMode = "disable"
}
if db.MaxOpenConns == 0 {
db.MaxOpenConns = 25
}
if db.MaxIdleConns == 0 {
db.MaxIdleConns = 5
}
if db.ConnMaxLifetime == 0 {
db.ConnMaxLifetime = 5 * time.Minute
}
if db.ConnMaxIdleTime == 0 {
db.ConnMaxIdleTime = 10 * time.Minute
}
if db.QueueCount == 0 {
db.QueueCount = 4
}
}
}
// ToPostgresConfig converts DatabaseConfig to adapter.PostgresConfig
func (d *DatabaseConfig) ToPostgresConfig() adapter.PostgresConfig {
return adapter.PostgresConfig{
Host: d.Host,
Port: d.Port,
Database: d.Database,
User: d.User,
Password: d.Password,
SSLMode: d.SSLMode,
MaxOpenConns: d.MaxOpenConns,
MaxIdleConns: d.MaxIdleConns,
ConnMaxLifetime: d.ConnMaxLifetime,
ConnMaxIdleTime: d.ConnMaxIdleTime,
}
}