Class: Pcrd::AdvisoryLock
- Inherits:
-
Object
- Object
- Pcrd::AdvisoryLock
- Defined in:
- lib/pcrd/advisory_lock.rb
Overview
A PostgreSQL session-level advisory lock used to stop two ‘pcrd migrate` processes from running against the same replication slot at once — which would corrupt checkpoint/LSN progress and fight over the slot.
The lock is taken on the source database (where the slot and publication live, the truly shared resource) and is keyed by the slot name. Being session-level, it is released by #release or automatically when the connection closes, so a crashed run does not leave it stuck.
Constant Summary collapse
- NAMESPACE =
"pcrd-migrate"
Instance Method Summary collapse
- #held? ⇒ Boolean
-
#initialize(pool:, name:) ⇒ AdvisoryLock
constructor
A new instance of AdvisoryLock.
-
#release ⇒ Object
Releases the lock if held.
-
#try_acquire ⇒ Object
Tries to take the lock without blocking.
Constructor Details
#initialize(pool:, name:) ⇒ AdvisoryLock
Returns a new instance of AdvisoryLock.
15 16 17 18 19 |
# File 'lib/pcrd/advisory_lock.rb', line 15 def initialize(pool:, name:) @pool = pool @name = name @held = false end |
Instance Method Details
#held? ⇒ Boolean
40 41 42 |
# File 'lib/pcrd/advisory_lock.rb', line 40 def held? @held end |
#release ⇒ Object
Releases the lock if held. Best-effort: a closed connection has already dropped it.
31 32 33 34 35 36 37 38 |
# File 'lib/pcrd/advisory_lock.rb', line 31 def release return unless @held @pool.exec("SELECT pg_advisory_unlock(hashtext($1)::bigint)", [key]) @held = false rescue Connection::Error nil end |
#try_acquire ⇒ Object
Tries to take the lock without blocking. Returns true if acquired, false if another session already holds it.
23 24 25 26 27 |
# File 'lib/pcrd/advisory_lock.rb', line 23 def try_acquire row = @pool.exec("SELECT pg_try_advisory_lock(hashtext($1)::bigint) AS locked", [key]) @held = (row[0]["locked"] == "t") @held end |