Class: Pcrd::AdvisoryLock

Inherits:
Object
  • Object
show all
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

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

Returns:

  • (Boolean)


40
41
42
# File 'lib/pcrd/advisory_lock.rb', line 40

def held?
  @held
end

#releaseObject

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_acquireObject

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