package database import ( "api_yal/internal/config" "api_yal/migrations" "database/sql" "fmt" "time" "github.com/golang-migrate/migrate/v4" "github.com/golang-migrate/migrate/v4/database/postgres" "github.com/golang-migrate/migrate/v4/source/iofs" "go.uber.org/zap" "gorm.io/driver/postgres" "gorm.io/gorm" "api_yal/internal/logger" ) func NewPostgresConnection(cfg *config.Config) (*gorm.DB, error) { zapLogger := logger.Get() zapLogger.Info("Start connect to Postgres DB") dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=UTC", cfg.DBHost, cfg.DBUser, cfg.DBPassword, cfg.DBName, cfg.DBPort) zapLogger.Info("dsn = %s", zap.String("dsn", dsn)) db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) if err != nil { return nil, fmt.Errorf("failed to connect to database: %w", err) } zapLogger.Info("Configure connection pool") sqlDB, err := db.DB() if err != nil { return nil, fmt.Errorf("failed to get underlying sql.DB: %w", err) } sqlDB.SetMaxOpenConns(25) sqlDB.SetMaxIdleConns(10) sqlDB.SetConnMaxLifetime(30 * time.Minute) zapLogger.Info("Run database migrations") if err := runMigrations(sqlDB); err != nil { return nil, fmt.Errorf("failed to run migrations: %w", err) } zapLogger.Info("Migrations completed successfully") zapLogger.Info("Successfully connected to database") return db, nil } func runMigrations(sqlDB *sql.DB) error { zapLogger := logger.Get() source, err := iofs.New(migrations.FS, ".") if err != nil { return fmt.Errorf("failed to create migration source: %w", err) } driver, err := postgres.WithInstance(sqlDB, &postgres.Config{}) if err != nil { return fmt.Errorf("failed to create postgres driver: %w", err) } m, err := migrate.NewWithInstance("iofs", source, "postgres", driver) if err != nil { return fmt.Errorf("failed to create migrate instance: %w", err) } if err := m.Up(); err != nil && err != migrate.ErrNoChange { zapLogger.Error("Migration error", zap.Error(err)) return fmt.Errorf("failed to apply migrations: %w", err) } return nil }