-
Notifications
You must be signed in to change notification settings - Fork 291
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2197 from josephschorr/fix-pg-migrations
make index creation idempotent
- Loading branch information
Showing
6 changed files
with
95 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package migrations | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/jackc/pgx/v5" | ||
|
||
"github.com/authzed/spicedb/internal/datastore/postgres/common" | ||
) | ||
|
||
const createIndexTemplate = ` | ||
CREATE INDEX CONCURRENTLY | ||
%s | ||
ON | ||
%s` | ||
|
||
const dropIndexTemplate = ` | ||
DROP INDEX CONCURRENTLY IF EXISTS | ||
%s; | ||
` | ||
|
||
const timeoutMessage = "This typically indicates that your database global statement_timeout needs to be increased and/or spicedb migrate command needs --migration-timeout increased (1h by default)" | ||
|
||
// createIndexConcurrently creates an index concurrently, dropping the existing index if it exists to ensure | ||
// that indexes are not left in a partially constructed state. | ||
// See: https://www.shayon.dev/post/2024/225/stop-relying-on-if-not-exists-for-concurrent-index-creation-in-postgresql/ | ||
func createIndexConcurrently(ctx context.Context, conn *pgx.Conn, indexName, creationClause string) error { | ||
dropIndexSQL := fmt.Sprintf(dropIndexTemplate, indexName) | ||
if _, err := conn.Exec(ctx, dropIndexSQL); err != nil { | ||
if common.IsQueryCanceledError(err) { | ||
return fmt.Errorf( | ||
"timed out while trying to drop index %s before recreating it: %w. %s", | ||
indexName, | ||
err, | ||
timeoutMessage, | ||
) | ||
} | ||
|
||
return fmt.Errorf("failed to drop index %s before creating it: %w", indexName, err) | ||
} | ||
|
||
createIndexSQL := fmt.Sprintf(createIndexTemplate, indexName, creationClause) | ||
if _, err := conn.Exec(ctx, createIndexSQL); err != nil { | ||
if common.IsQueryCanceledError(err) { | ||
return fmt.Errorf( | ||
"timed out while trying to create index %s: %w. %s", | ||
indexName, | ||
err, | ||
timeoutMessage, | ||
) | ||
} | ||
|
||
return fmt.Errorf("failed to create index %s: %w", indexName, err) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
internal/datastore/postgres/migrations/zz_migration.0022_add_expiration_index.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package migrations | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/jackc/pgx/v5" | ||
) | ||
|
||
// Used for cleaning up expired relationships. | ||
const expiredRelationshipsIndex = ` | ||
relation_tuple (expiration) | ||
WHERE expiration IS NOT NULL; | ||
` | ||
|
||
func init() { | ||
if err := DatabaseMigrations.Register("add-expiration-cleanup-index", "add-expiration-support", | ||
func(ctx context.Context, conn *pgx.Conn) error { | ||
return createIndexConcurrently(ctx, conn, "ix_relation_tuple_expired", expiredRelationshipsIndex) | ||
}, | ||
noTxMigration); err != nil { | ||
panic("failed to register migration: " + err.Error()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters