newdrive/internal/adapters/postgres/migrate.go
Elijah 077cf7601a
Some checks failed
CI / Backend (push) Failing after 4s
CI / Frontend (push) Successful in 11s
CI / Contracts and repository policy (push) Failing after 5s
CI / Container (push) Has been skipped
Initial phase 1 baseline implementation
2026-07-16 19:14:01 -07:00

56 lines
1.5 KiB
Go

package postgres
import (
"errors"
"fmt"
"net/url"
"drive.local/drivev2/db/migrations"
"github.com/golang-migrate/migrate/v4"
pgx5migrate "github.com/golang-migrate/migrate/v4/database/pgx/v5"
"github.com/golang-migrate/migrate/v4/source/iofs"
)
// Migrate applies every pending forward migration using an advisory lock.
func Migrate(databaseURL string) (returnErr error) {
sourceDriver, err := iofs.New(migrations.Files, ".")
if err != nil {
return fmt.Errorf("open embedded migrations: %w", err)
}
migrationURL, err := url.Parse(databaseURL)
if err != nil {
return fmt.Errorf("parse database URL for migrations: %w", err)
}
migrationURL.Scheme = "pgx5"
query := migrationURL.Query()
query.Set("x-multi-statement", "true")
query.Set("x-statement-timeout", "30000")
if query.Get("connect_timeout") == "" {
query.Set("connect_timeout", "30")
}
migrationURL.RawQuery = query.Encode()
databaseDriver, err := (&pgx5migrate.Postgres{}).Open(migrationURL.String())
if err != nil {
return fmt.Errorf("open migration database: %w", err)
}
runner, err := migrate.NewWithInstance("iofs", sourceDriver, "pgx5", databaseDriver)
if err != nil {
return errors.Join(
fmt.Errorf("create migration runner: %w", err),
sourceDriver.Close(),
databaseDriver.Close(),
)
}
defer func() {
sourceErr, databaseErr := runner.Close()
returnErr = errors.Join(returnErr, sourceErr, databaseErr)
}()
if err := runner.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
return fmt.Errorf("apply database migrations: %w", err)
}
return nil
}