package configstore import ( "context" "fmt" "github.com/maximhq/bifrost/core/schemas" "gorm.io/driver/postgres" "gorm.io/gorm" ) // PostgresConfig represents the configuration for a Postgres database. type PostgresConfig struct { Host *schemas.EnvVar `json:"host"` Port *schemas.EnvVar `json:"port"` User *schemas.EnvVar `json:"user"` Password *schemas.EnvVar `json:"password"` DBName *schemas.EnvVar `json:"db_name"` SSLMode *schemas.EnvVar `json:"ssl_mode"` MaxIdleConns int `json:"max_idle_conns"` MaxOpenConns int `json:"max_open_conns"` } // newPostgresConfigStore creates a new Postgres config store. func newPostgresConfigStore(ctx context.Context, config *PostgresConfig, logger schemas.Logger) (ConfigStore, error) { if config == nil { return nil, fmt.Errorf("config is required") } // Validate required config if config.Host == nil || config.Host.GetValue() == "" { return nil, fmt.Errorf("postgres host is required") } if config.Port == nil || config.Port.GetValue() == "" { return nil, fmt.Errorf("postgres port is required") } if config.User == nil || config.User.GetValue() == "" { return nil, fmt.Errorf("postgres user is required") } if config.Password == nil { return nil, fmt.Errorf("postgres password is required") } if config.DBName == nil || config.DBName.GetValue() == "" { return nil, fmt.Errorf("postgres db name is required") } if config.SSLMode == nil || config.SSLMode.GetValue() == "" { return nil, fmt.Errorf("postgres ssl mode is required") } dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s", config.Host.GetValue(), config.Port.GetValue(), config.User.GetValue(), config.Password.GetValue(), config.DBName.GetValue(), config.SSLMode.GetValue()) db, err := gorm.Open(postgres.New(postgres.Config{ DSN: dsn, }), &gorm.Config{ Logger: newGormLogger(logger), }) if err != nil { return nil, err } // Configure connection pool sqlDB, err := db.DB() if err != nil { return nil, err } // Set MaxIdleConns (default: 5) maxIdleConns := config.MaxIdleConns if maxIdleConns == 0 { maxIdleConns = 5 } sqlDB.SetMaxIdleConns(maxIdleConns) // Set MaxOpenConns (default: 50) maxOpenConns := config.MaxOpenConns if maxOpenConns == 0 { maxOpenConns = 50 } sqlDB.SetMaxOpenConns(maxOpenConns) d := &RDBConfigStore{db: db, logger: logger} // Run migrations if err := triggerMigrations(ctx, db); err != nil { // Closing the DB connection if sqlDB, dbErr := db.DB(); dbErr == nil { if closeErr := sqlDB.Close(); closeErr != nil { logger.Error("failed to close DB connection: %v", closeErr) } } return nil, err } // Encrypt any plaintext rows if encryption is enabled if err := d.EncryptPlaintextRows(ctx); err != nil { if sqlDB, dbErr := db.DB(); dbErr == nil { if closeErr := sqlDB.Close(); closeErr != nil { logger.Error("failed to close DB connection: %v", closeErr) } } return nil, fmt.Errorf("failed to encrypt plaintext rows: %w", err) } return d, nil }