aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2026-08-05 19:43:42 +0200
committerStefan Majewsky <majewsky@gmx.net>2026-08-05 19:43:42 +0200
commit972e3e4fbd88ace9494b6a8c639119852770636b (patch)
treeb8a7459e947ce367ef58226b6b92297180633327
parent8bb08a0847eff3e92044685307cd620674b9b4ff (diff)
downloadgo-gg-972e3e4fbd88ace9494b6a8c639119852770636b.tar.gz
pgruntime: protect against concurrent migrations
-rw-r--r--CHANGELOG.md6
-rw-r--r--pgruntime/behavior.go17
2 files changed, 22 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77b3972..e7bfdf6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,12 @@ SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net>
SPDX-License-Identifier: Apache-2.0
-->
+# v1.13.2 (TBD)
+
+Changes:
+
+- pgruntime: Add transaction locking to protect against concurrent migrations.
+
# v1.13.1 (2026-08-05)
Changes:
diff --git a/pgruntime/behavior.go b/pgruntime/behavior.go
index 3ffff1e..03ff338 100644
--- a/pgruntime/behavior.go
+++ b/pgruntime/behavior.go
@@ -110,7 +110,22 @@ func applyMigrations(ctx context.Context, db gsql.ConnectionHandle, migrations m
// apply migrations
for _, version := range pendingVersions {
err := db.GSQLTransact(ctx, func(tx gsql.Handle) error {
- _, err := execQuery(ctx, db, migrations[version], nil)
+ // ensure that nobody else is migrating until we are done
+ var actualVersion int64
+ err := queryRow(ctx, db, `SELECT version FROM schema_migrations FOR UPDATE`, nil, []any{&actualVersion})
+ if err != nil {
+ return fmt.Errorf("could not obtain lock for schema migration: %w", err)
+ }
+
+ // ensure that nobody else migrated just before we started our transaction block
+ if version <= actualVersion {
+ return fmt.Errorf("tried to perform migration to version %d, but schema is already at version %d (multiple migrations might be running concurrently)",
+ version, actualVersion,
+ )
+ }
+
+ // perform the next migration
+ _, err = execQuery(ctx, db, migrations[version], nil)
if err != nil {
return fmt.Errorf("could not execute schema migration: %w", err)
}