Skip to content

fix: pin connection for advisory lock lifecycle#1168

Open
thetutlage wants to merge 2 commits into22.xfrom
fix/advisory-lock-connection-pinning
Open

fix: pin connection for advisory lock lifecycle#1168
thetutlage wants to merge 2 commits into22.xfrom
fix/advisory-lock-connection-pinning

Conversation

@thetutlage
Copy link
Copy Markdown
Member

Summary

  • Advisory locks are session-scoped (bound to the database connection that acquired them), but rawQuery picks a random connection from the pool each time. This causes releaseAdvisoryLock to fail with E_UNABLE_RELEASE_LOCK when it lands on a different connection than getAdvisoryLock.
  • When pool max > 1, the migration runner now pins a dedicated connection and passes it to the dialect's lock methods. With pool max = 1, pinning is skipped (unnecessary and would starve other queries).
  • Dialect getAdvisoryLock and releaseAdvisoryLock accept an optional connection parameter to use a specific connection instead of acquiring one from the pool.

Closes #1153

Test plan

  • Pool of 1: holding a connection starves the pool (proves pinning must be conditional)
  • Pool of 2 without pinned connection: release fails (proves the bug)
  • Pool of 2 with pinned connection: release succeeds (proves the fix)
  • Migration runner with pool of 4: full migration cycle completes
  • Migration runner with pool of 1: full migration cycle completes
  • All existing migration and query client tests pass

Allow overwriting existing files during stub generation by passing
--force to any make:* command. The make:model command forwards the
flag to sub-commands (migration, controller, transformer, factory).
…ELEASE_LOCK

Advisory locks (PG_TRY_ADVISORY_LOCK/PG_ADVISORY_UNLOCK in PostgreSQL,
GET_LOCK/RELEASE_LOCK in MySQL) are session-scoped — they are bound to
the specific database connection that acquired them. Previously, both
acquire and release used rawQuery which picks a random connection from
the pool each time, causing the release to fail when it lands on a
different connection.

When the pool has more than one connection, the migration runner now
pins a dedicated connection and passes it through to the dialect's lock
methods. With a single-connection pool, pinning is skipped since it
would starve other queries and isn't needed (only one connection exists).

Closes #1153
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Advisory lock for migrations acquires and releases on different pool connections, causing E_UNABLE_RELEASE_LOCK

1 participant