Skip to content

Commit

Permalink
feat(migrate): add pending migrations function
Browse files Browse the repository at this point in the history
  • Loading branch information
JustSamuel committed Aug 30, 2024
1 parent c6a436b commit bb07e01
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 1 deletion.
2 changes: 1 addition & 1 deletion gocqlxtest/gocqlxtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
)

var (
flagCluster = flag.String("cluster", "127.0.0.1", "a comma-separated list of host:port tuples")
flagCluster = flag.String("cluster", "127.3.0.5", "a comma-separated list of host:port tuples")
flagKeyspace = flag.String("keyspace", "gocqlx_test", "keyspace name")
flagProto = flag.Int("proto", 0, "protcol version")
flagCQL = flag.String("cql", "3.0.0", "CQL version")
Expand Down
6 changes: 6 additions & 0 deletions migrate/example/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ func TestExample(t *testing.T) {
reg.Add(migrate.CallComment, "3", log)
migrate.Callback = reg.Callback

pending, err := migrate.Pending(context.Background(), session, cql.Files)
if err != nil {
t.Fatal("Pending:", err)
}
t.Log("Pending migrations:", len(pending))

// First run prints data
if err := migrate.FromFS(context.Background(), session, cql.Files); err != nil {
t.Fatal("Migrate:", err)
Expand Down
42 changes: 42 additions & 0 deletions migrate/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,48 @@ func List(ctx context.Context, session gocqlx.Session) ([]*Info, error) {
return v, nil
}

// Pending provides a listing of pending migrations.
func Pending(ctx context.Context, session gocqlx.Session, f fs.FS) ([]*Info, error) {
applied, err := List(ctx, session)
if err != nil {
return nil, err
}

fm, err := fs.Glob(f, "*.cql")
if err != nil {
return nil, fmt.Errorf("list migrations: %w", err)
}

if len(applied) > len(fm) {
return nil, fmt.Errorf("database is ahead")
}

pending := make([]*Info, 0, len(fm)-len(applied))

for i := range applied {
if applied[i].Name != fm[i] {
return nil, fmt.Errorf("inconsistent migrations found, expected %q got %q at %d", applied[i].Name, fm[i], i)
}
}

for _, name := range fm[len(applied):] {
c, err := fileChecksum(f, name)
if err != nil {
return nil, fmt.Errorf("calculate checksum for %q: %w", name, err)
}

info := &Info{
Name: filepath.Base(name),
StartTime: time.Now(),
Checksum: c,
}

pending = append(pending, info)
}

return pending, nil
}

func ensureInfoTable(ctx context.Context, session gocqlx.Session) error {
return session.ContextQuery(ctx, infoSchema, nil).ExecRelease()
}
Expand Down
83 changes: 83 additions & 0 deletions migrate/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,89 @@ func recreateTables(tb testing.TB, session gocqlx.Session) {
}
}

func TestPending(t *testing.T) {
session := gocqlxtest.CreateSession(t)
defer session.Close()
recreateTables(t, session)

ctx := context.Background()

t.Run("ahead", func(t *testing.T) {
defer recreateTables(t, session)

if err := migrate.FromFS(ctx, session, makeTestFS(4)); err != nil {
t.Fatal(err)
}

_, err := migrate.Pending(ctx, session, makeTestFS(2))

if err == nil || !strings.Contains(err.Error(), "ahead") {
t.Fatal("expected error")
} else {
t.Log(err)
}
})

t.Run("inconsistent", func(t *testing.T) {
defer recreateTables(t, session)

if err := migrate.FromFS(ctx, session, makeTestFS(1)); err != nil {
t.Fatal(err)
}

f := memfs.New()
writeFile(f, 1, fmt.Sprintf(insertMigrate, 1)+";")

_, err := migrate.Pending(ctx, session, f)

if err == nil || !strings.Contains(err.Error(), "inconsistent") {
t.Fatal("expected error")
} else {
t.Log(err)
}
})

t.Run("pending", func(t *testing.T) {
defer recreateTables(t, session)

f := memfs.New()
writeFile(f, 0, fmt.Sprintf(insertMigrate, 0)+";")

pending, err := migrate.Pending(ctx, session, f)
if err != nil {
t.Fatal(err)
}
if len(pending) != 1 {
t.Fatal("expected 2 pending migrations got", len(pending))
}

err = migrate.FromFS(ctx, session, f)
if err != nil {
t.Fatal(err)
}

pending, err = migrate.Pending(ctx, session, f)
if err != nil {
t.Fatal(err)
}
if len(pending) != 0 {
t.Fatal("expected no pending migrations got", len(pending))
}

for i := 1; i < 3; i++ {
writeFile(f, i, fmt.Sprintf(insertMigrate, i)+";")
}

pending, err = migrate.Pending(ctx, session, f)
if err != nil {
t.Fatal(err)
}
if len(pending) != 2 {
t.Fatal("expected 2 pending migrations got", len(pending))
}
})
}

func TestMigration(t *testing.T) {
session := gocqlxtest.CreateSession(t)
defer session.Close()
Expand Down

0 comments on commit bb07e01

Please sign in to comment.