Skip to content

Commit

Permalink
Merge pull request #1203 from Quentinchampenois/fix/pending_migrations
Browse files Browse the repository at this point in the history
Execute all pending migrations regardless of their timestamp
  • Loading branch information
mattwoberts authored Sep 16, 2024
2 parents a9c05c5 + 1d446b9 commit 42c9a98
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 12 deletions.
52 changes: 40 additions & 12 deletions app/pkg/dbx/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"context"
"database/sql"
stdErrors "errors"
"github.com/lib/pq"
"os"
"slices"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -63,20 +65,23 @@ func Migrate(ctx context.Context, path string) error {

totalMigrationsExecuted := 0

pendingVersions, err := getPendingMigrations(versions)
if err != nil {
return errors.Wrap(err, "failed to get pending migrations")
}

// Apply all migrations
for _, version := range versions {
if version > lastVersion {
fileName := versionFiles[version]
log.Infof(ctx, "Running Version: @{Version} (@{FileName})", dto.Props{
"Version": version,
"FileName": fileName,
})
err := runMigration(ctx, version, path, fileName)
if err != nil {
return errors.Wrap(err, "failed to run migration '%s'", fileName)
}
totalMigrationsExecuted++
for _, version := range pendingVersions {
fileName := versionFiles[version]
log.Infof(ctx, "Running Version: @{Version} (@{FileName})", dto.Props{
"Version": version,
"FileName": fileName,
})
err := runMigration(ctx, version, path, fileName)
if err != nil {
return errors.Wrap(err, "failed to run migration '%s'", fileName)
}
totalMigrationsExecuted++
}

if totalMigrationsExecuted > 0 {
Expand Down Expand Up @@ -140,3 +145,26 @@ func getLastMigration() (int, error) {

return int(lastVersion.Int64), nil
}

func getPendingMigrations(versions []int) ([]int, error) {
pendingMigrations := append([]int(nil), versions...)

rows, err := conn.Query("SELECT version FROM migrations_history WHERE version = ANY($1)", pq.Array(pendingMigrations))
if err != nil {
return nil, err
}
defer rows.Close()

for rows.Next() {
var version int
if err := rows.Scan(&version); err != nil {
return nil, errors.Wrap(err, "failed to scan version")
}
i := slices.Index(pendingMigrations, version)
if i != -1 {
pendingMigrations = slices.Delete(pendingMigrations, i, i+1)
}
}

return pendingMigrations, nil
}
24 changes: 24 additions & 0 deletions app/pkg/dbx/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,30 @@ func TestMigrate_Success(t *testing.T) {
trx.MustRollback()
}

func TestMigrate_SuccessWithPastMigration(t *testing.T) {
setupMigrationTest(t)
ctx := context.Background()

err := dbx.Migrate(ctx, "/app/pkg/dbx/testdata/migration_success")
Expect(err).IsNil()

err = dbx.Migrate(ctx, "/app/pkg/dbx/testdata/migration_success_with_new_migrations")
Expect(err).IsNil()

trx, _ := dbx.BeginTx(ctx)
var version string
err = trx.Scalar(&version, "SELECT version FROM migrations_history WHERE version = '209901010000' LIMIT 1")
Expect(err).IsNil()
Expect(version).Equals("209901010000")

var count int
err = trx.Scalar(&count, "SELECT COUNT(*) FROM migrations_history WHERE version IN (209901010000,210001010002)")
Expect(err).IsNil()
Expect(count).Equals(2)

trx.MustRollback()
}

func TestMigrate_Failure(t *testing.T) {
setupMigrationTest(t)
ctx := context.Background()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
insert into dummy (id, description) values (400, 'Description 400A');
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM dummy WHERE id = 400;

0 comments on commit 42c9a98

Please sign in to comment.