package config import ( "log" "os" "strings" "time" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" ) var DB *gorm.DB func ConnectDatabase() { dsn := GlobalConfig.DatabaseURL // Bersihkan skema psycopg dari Python jika ada if strings.HasPrefix(dsn, "postgresql+psycopg://") { dsn = strings.Replace(dsn, "postgresql+psycopg://", "postgres://", 1) } else if strings.HasPrefix(dsn, "postgresql://") { dsn = strings.Replace(dsn, "postgresql://", "postgres://", 1) } log.Printf("Connecting to database: %s", sanitizeDSN(dsn)) logLevel := logger.Warn if strings.ToLower(os.Getenv("DEBUG")) == "true" || strings.ToLower(os.Getenv("GORM_LOG_LEVEL")) == "info" { logLevel = logger.Info } newLogger := logger.New( log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ SlowThreshold: 1500 * time.Millisecond, // Batas lambat 1.5 detik demi mengakomodasi latensi cross-region internet LogLevel: logLevel, IgnoreRecordNotFoundError: true, Colorful: true, }, ) var err error DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{ Logger: newLogger, }) if err != nil { log.Fatalf("Gagal menghubungkan ke database: %v", err) } log.Println("Berhasil terhubung ke database!") // Konfigurasi connection pool sqlDB, err := DB.DB() if err != nil { log.Fatalf("Gagal mengambil instance SQL DB: %v", err) } // Atur batas pool yang efisien untuk mencegah kelelahan koneksi Supabase & latensi tinggi sqlDB.SetMaxIdleConns(4) sqlDB.SetMaxOpenConns(20) sqlDB.SetConnMaxIdleTime(10 * time.Minute) sqlDB.SetConnMaxLifetime(time.Hour) } func sanitizeDSN(dsn string) string { // Sembunyikan password dalam log demi alasan keamanan if strings.Contains(dsn, "@") { parts := strings.Split(dsn, "@") credentials := strings.Split(parts[0], "://") if len(credentials) == 2 { userPass := strings.Split(credentials[1], ":") if len(userPass) == 2 { return credentials[0] + "://" + userPass[0] + ":******@" + parts[1] } } } return dsn }