Skip to content

Commit 4983f86

Browse files
improvement(db): re-verify advisory-lock session before script migrations
1 parent a39cf8e commit 4983f86

1 file changed

Lines changed: 18 additions & 9 deletions

File tree

packages/db/scripts/migrate.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ try {
112112
try {
113113
await runMigrationsWithRetry()
114114
console.log('Migrations applied successfully.')
115+
await assertLockSessionHeld()
115116
await runScriptMigrations(client)
116117
await warnOnInvalidIndexes()
117118
} finally {
@@ -181,17 +182,25 @@ async function acquireMigrationLock(): Promise<void> {
181182
* Replays are safe: drizzle rolls the batch back on failure, and post-COMMIT
182183
* CONCURRENTLY statements are idempotent by convention.
183184
*/
185+
/**
186+
* Verify the session still holds the migration advisory lock: a changed
187+
* backend pid means the connection was recycled and the lock silently dropped.
188+
* Only sound on a direct connection — see `hasDirectMigrationUrl`.
189+
*/
190+
async function assertLockSessionHeld(): Promise<void> {
191+
if (!hasDirectMigrationUrl) return
192+
const [{ pid }] = await client`SELECT pg_backend_pid() AS pid`
193+
if (pid !== lockSessionPid) {
194+
throw new Error(
195+
`Database session changed mid-run (backend pid ${lockSessionPid} -> ${pid}); ` +
196+
'the migration advisory lock was lost. Aborting so a fresh runner can retry safely.'
197+
)
198+
}
199+
}
200+
184201
async function runMigrationsWithRetry(): Promise<void> {
185202
for (let attempt = 1; ; attempt++) {
186-
if (hasDirectMigrationUrl) {
187-
const [{ pid }] = await client`SELECT pg_backend_pid() AS pid`
188-
if (pid !== lockSessionPid) {
189-
throw new Error(
190-
`Database session changed mid-run (backend pid ${lockSessionPid} -> ${pid}); ` +
191-
'the migration advisory lock was lost. Aborting so a fresh runner can retry safely.'
192-
)
193-
}
194-
}
203+
await assertLockSessionHeld()
195204
await client.unsafe('SET statement_timeout = 0')
196205
await client.unsafe(`SET lock_timeout = '${DDL_LOCK_TIMEOUT}'`)
197206
try {

0 commit comments

Comments
 (0)