package config import ( "fmt" "log" "sync" "time" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" ) var ( db *gorm.DB once sync.Once dbErr error ) // GetDB retorna la conexión a la base de datos func GetDatabaseConnection(cfg *Config) *gorm.DB { once.Do(func() { dsn := fmt.Sprintf( "host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", cfg.DBHost, cfg.DBPort, cfg.DBUser, cfg.DBPassword, cfg.DBName, ) // Reintentos automáticos maxRetries := 3 for i := 0; i < maxRetries; i++ { db, dbErr = gorm.Open(postgres.Open(dsn), &gorm.Config{ Logger: logger.Default.LogMode(logger.Silent), }) if dbErr == nil { break } log.Printf("⚠️ Intento %d de conexión fallido: %v", i+1, dbErr) time.Sleep(2 * time.Second) } if dbErr != nil { log.Fatalf("❌ No se pudo conectar a la BD después de varios intentos: %v", dbErr) } // Configuración del pool sqlDB, err := db.DB() if err != nil { log.Fatalf("❌ Error al obtener objeto SQL: %v", err) } // Validación inmediata if err := sqlDB.Ping(); err != nil { log.Fatalf("❌ Error al hacer ping a la BD: %v", err) } sqlDB.SetMaxOpenConns(cfg.DBMaxOpenConns) // Conexiones máximas sqlDB.SetMaxIdleConns(cfg.DBMaxIdleConns) // Conexiones inactivas permitidas sqlDB.SetConnMaxLifetime(cfg.DBConnMaxLifetime * time.Minute) // Tiempo máximo de vida log.Println("✅ Conexión a la BD establecida correctamente") }) return db }