package db import ( "eslogad-be/config" "fmt" "io/fs" "os" "path/filepath" "sort" _ "github.com/lib/pq" "go.uber.org/zap" _ "gopkg.in/yaml.v3" "gorm.io/driver/postgres" "gorm.io/gorm" ) func NewPostgres(c config.Database) (*gorm.DB, error) { dialector := postgres.New(postgres.Config{ DSN: c.DSN(), }) db, err := gorm.Open(dialector, &gorm.Config{}) if err != nil { return nil, err } zapCfg := zap.NewProductionConfig() zapCfg.Level = zap.NewAtomicLevelAt(zap.ErrorLevel) zapCfg.DisableCaller = false sqlDB, err := db.DB() if err != nil { return nil, err } if err := sqlDB.Ping(); err != nil { return nil, err } sqlDB.SetMaxIdleConns(c.MaxIdleConnectionsInSecond) sqlDB.SetMaxOpenConns(c.MaxOpenConnectionsInSecond) sqlDB.SetConnMaxLifetime(c.ConnectionMaxLifetime()) fmt.Println("Successfully connected to PostgreSQL database") return db, nil } func runMigrations(sqlDB *gorm.DB) error { // use the underlying *sql.DB for Exec db := sqlDB sqlConn, err := db.DB() if err != nil { return err } migrationsDir := "migrations" entries := []string{} if err := filepath.WalkDir(migrationsDir, func(path string, d fs.DirEntry, walkErr error) error { if walkErr != nil { return walkErr } if d.IsDir() { return nil } if filepath.Ext(d.Name()) == ".sql" { entries = append(entries, path) } return nil }); err != nil && !os.IsNotExist(err) { return err } // sort by name to ensure order sort.Strings(entries) for _, file := range entries { contents, err := os.ReadFile(file) if err != nil { return fmt.Errorf("read migration %s: %w", file, err) } if _, err := sqlConn.Exec(string(contents)); err != nil { return fmt.Errorf("exec migration %s: %w", file, err) } fmt.Printf("Applied migration: %s\n", filepath.Base(file)) } return nil }