Skip to content

Commit

Permalink
fix: set lock timeout when migrating history schema (#2023)
Browse files Browse the repository at this point in the history
* fix: set lock timeout when migrating history schema

* chore: refactor creating migration history table
  • Loading branch information
sweatybridge authored Mar 7, 2024
1 parent 243db97 commit 4a64560
Show file tree
Hide file tree
Showing 8 changed files with 29 additions and 22 deletions.
1 change: 1 addition & 0 deletions internal/gen/types/typescript/typescript.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func Run(ctx context.Context, projectId string, dbConfig pgconn.Config, schemas
}

fmt.Fprintln(os.Stderr, "Connecting to", dbConfig.Host, dbConfig.Port)
// pg-meta does not set username as the default database, ie. postgres
if len(dbConfig.Database) == 0 {
dbConfig.Database = "postgres"
}
Expand Down
4 changes: 2 additions & 2 deletions internal/link/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/spf13/viper"
"github.com/supabase/cli/internal/migration/repair"
"github.com/supabase/cli/internal/migration/history"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/credentials"
"github.com/supabase/cli/internal/utils/flags"
Expand Down Expand Up @@ -184,7 +184,7 @@ func linkDatabase(ctx context.Context, config pgconn.Config, options ...func(*pg
defer conn.Close(context.Background())
updatePostgresConfig(conn)
// If `schema_migrations` doesn't exist on the remote database, create it.
return repair.CreateMigrationTable(ctx, conn)
return history.CreateMigrationTable(ctx, conn)
}

func linkDatabaseVersion(ctx context.Context, projectRef string, fsys afero.Fs) error {
Expand Down
3 changes: 2 additions & 1 deletion internal/link/link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,8 @@ func TestLinkDatabase(t *testing.T) {
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(history.CREATE_VERSION_SCHEMA).
conn.Query(history.SET_LOCK_TIMEOUT).
Query(history.CREATE_VERSION_SCHEMA).
Reply("CREATE SCHEMA").
Query(history.CREATE_VERSION_TABLE).
ReplyError(pgerrcode.InsufficientPrivilege, "permission denied for relation supabase_migrations").
Expand Down
3 changes: 2 additions & 1 deletion internal/migration/apply/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/migration/history"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/migration/repair"
"github.com/supabase/cli/internal/utils"
Expand Down Expand Up @@ -40,7 +41,7 @@ func SeedDatabase(ctx context.Context, conn *pgx.Conn, fsys afero.Fs) error {

func MigrateUp(ctx context.Context, conn *pgx.Conn, pending []string, fsys afero.Fs) error {
if len(pending) > 0 {
if err := repair.CreateMigrationTable(ctx, conn); err != nil {
if err := history.CreateMigrationTable(ctx, conn); err != nil {
return err
}
}
Expand Down
20 changes: 17 additions & 3 deletions internal/migration/history/history.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package history

import "github.com/jackc/pgconn"
import (
"context"

"github.com/go-errors/errors"
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
)

const (
SET_LOCK_TIMEOUT = "SET LOCAL lock_timeout = '4s'"
CREATE_VERSION_SCHEMA = "CREATE SCHEMA IF NOT EXISTS supabase_migrations"
CREATE_VERSION_TABLE = "CREATE TABLE IF NOT EXISTS supabase_migrations.schema_migrations (version text NOT NULL PRIMARY KEY)"
ADD_STATEMENTS_COLUMN = "ALTER TABLE supabase_migrations.schema_migrations ADD COLUMN IF NOT EXISTS statements text[]"
Expand All @@ -13,10 +20,17 @@ const (
TRUNCATE_VERSION_TABLE = "TRUNCATE supabase_migrations.schema_migrations"
)

func AddCreateTableStatements(batch *pgconn.Batch) {
// Create history table if not exists
func CreateMigrationTable(ctx context.Context, conn *pgx.Conn) error {
// This must be run without prepared statements because each statement in the batch depends on
// the previous schema change. The lock timeout will be reset when implicit transaction ends.
batch := pgconn.Batch{}
batch.ExecParams(SET_LOCK_TIMEOUT, nil, nil, nil, nil)
batch.ExecParams(CREATE_VERSION_SCHEMA, nil, nil, nil, nil)
batch.ExecParams(CREATE_VERSION_TABLE, nil, nil, nil, nil)
batch.ExecParams(ADD_STATEMENTS_COLUMN, nil, nil, nil, nil)
batch.ExecParams(ADD_NAME_COLUMN, nil, nil, nil, nil)
if _, err := conn.PgConn().ExecBatch(ctx, &batch).ReadAll(); err != nil {
return errors.Errorf("failed to create migration table: %w", err)
}
return nil
}
15 changes: 2 additions & 13 deletions internal/migration/repair/repair.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,8 @@ func Run(ctx context.Context, config pgconn.Config, version []string, status str
}

func UpdateMigrationTable(ctx context.Context, conn *pgx.Conn, version []string, status string, repairAll bool, fsys afero.Fs) error {
schema := &pgconn.Batch{}
history.AddCreateTableStatements(schema)
if _, err := conn.PgConn().ExecBatch(ctx, schema).ReadAll(); err != nil {
return errors.Errorf("failed to create migration table: %w", err)
if err := history.CreateMigrationTable(ctx, conn); err != nil {
return err
}
// Data statements don't mutate schemas, safe to use statement cache
batch := &pgx.Batch{}
Expand Down Expand Up @@ -90,15 +88,6 @@ func UpdateMigrationTable(ctx context.Context, conn *pgx.Conn, version []string,
return nil
}

func CreateMigrationTable(ctx context.Context, conn *pgx.Conn) error {
batch := pgconn.Batch{}
history.AddCreateTableStatements(&batch)
if _, err := conn.PgConn().ExecBatch(ctx, &batch).ReadAll(); err != nil {
return errors.Errorf("failed to create migration table: %w", err)
}
return nil
}

func InsertVersionSQL(batch *pgconn.Batch, version, name string, stats []string) {
encoded := []byte{'{'}
for i, line := range stats {
Expand Down
2 changes: 1 addition & 1 deletion internal/migration/squash/squash.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func baselineMigrations(ctx context.Context, config pgconn.Config, version strin
return err
}
defer conn.Close(context.Background())
if err := repair.CreateMigrationTable(ctx, conn); err != nil {
if err := history.CreateMigrationTable(ctx, conn); err != nil {
return err
}
m, err := repair.NewMigrationFromVersion(version, fsys)
Expand Down
3 changes: 2 additions & 1 deletion internal/testing/pgtest/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import (
)

func MockMigrationHistory(conn *MockConn) {
conn.Query(history.CREATE_VERSION_SCHEMA).
conn.Query(history.SET_LOCK_TIMEOUT).
Query(history.CREATE_VERSION_SCHEMA).
Reply("CREATE SCHEMA").
Query(history.CREATE_VERSION_TABLE).
Reply("CREATE TABLE").
Expand Down

0 comments on commit 4a64560

Please sign in to comment.