181 lines
5.1 KiB
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,
|
|
}
|
|
}
|