package db import ( "fmt" "tercul/internal/observability" "tercul/internal/platform/config" "tercul/internal/platform/log" "time" "gorm.io/driver/postgres" "gorm.io/gorm" gormlogger "gorm.io/gorm/logger" ) // Connect establishes a connection to the database using the provided configuration. // It returns the database connection and any error encountered. func Connect(cfg *config.Config, metrics *observability.Metrics) (*gorm.DB, error) { log.Info(fmt.Sprintf("Connecting to database: host=%s db=%s", cfg.DBHost, cfg.DBName)) dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable", cfg.DBHost, cfg.DBUser, cfg.DBPassword, cfg.DBName, cfg.DBPort) db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ Logger: gormlogger.Default.LogMode(gormlogger.Warn), }) if err != nil { return nil, fmt.Errorf("failed to connect to database: %w", err) } // Register Prometheus plugin if err := db.Use(NewPrometheusPlugin(metrics)); err != nil { return nil, fmt.Errorf("failed to register prometheus plugin: %w", err) } // Get the underlying SQL DB instance sqlDB, err := db.DB() if err != nil { return nil, fmt.Errorf("failed to get SQL DB instance: %w", err) } // Set connection pool settings sqlDB.SetMaxOpenConns(20) // Connection pooling sqlDB.SetMaxIdleConns(5) // Idle connections sqlDB.SetConnMaxLifetime(30 * time.Minute) log.Info(fmt.Sprintf("Successfully connected to database: host=%s db=%s", cfg.DBHost, cfg.DBName)) return db, nil } // Close closes the database connection. func Close(db *gorm.DB) error { if db == nil { return nil } sqlDB, err := db.DB() if err != nil { return fmt.Errorf("failed to get SQL DB instance: %w", err) } return sqlDB.Close() } // InitDB initializes the database connection. func InitDB(cfg *config.Config, metrics *observability.Metrics) (*gorm.DB, error) { // Connect to the database db, err := Connect(cfg, metrics) if err != nil { return nil, err } return db, nil }