class PgLock

Constants

DEFAULT_CONNECTION_CONNECTOR
DEFAULT_LOGGER
NO_LOCK
PG_LOCK_SPACE
UnableToLock
VERSION

Attributes

attempt_interval[RW]
connection[RW]
locket[RW]
log[RW]
max_attempts[RW]
name[RW]
return_result[RW]
ttl[RW]

Public Class Methods

new(name:, attempts: 3, attempt_interval: 1, ttl: 60, connection: DEFAULT_CONNECTION_CONNECTOR.call, log: DEFAULT_LOGGER.call, return_result: true) click to toggle source
# File lib/pg_lock.rb, line 31
def initialize(name:, attempts: 3, attempt_interval: 1, ttl: 60, connection: DEFAULT_CONNECTION_CONNECTOR.call, log: DEFAULT_LOGGER.call, return_result: true)
  self.name               = name
  self.max_attempts       = [attempts, 1].max
  self.attempt_interval   = attempt_interval
  self.ttl                = ttl || 0 # set this to 0 to disable the timeout
  self.log                = log
  self.return_result      = return_result

  connection or raise "Must provide a valid connection object"
  self.locket             = Locket.new(connection, [PG_LOCK_SPACE, key(name)])
end

Public Instance Methods

acquired?() click to toggle source
# File lib/pg_lock.rb, line 87
def acquired?
  locket.active?
end
Also aliased as: has_lock?
aquired?() click to toggle source

Left the misspelled version of this method for backwards compatibility

# File lib/pg_lock.rb, line 83
def aquired?
  acquired?
end
create() click to toggle source
# File lib/pg_lock.rb, line 59
def create
  max_attempts.times.each do |attempt|
    if locket.lock
      log.call(at: :create, attempt: attempt, args: locket.args, pg_lock: true) if log
      return self
    else
      return false if attempt.next == max_attempts
      sleep attempt_interval
    end
  end
end
delete() click to toggle source
# File lib/pg_lock.rb, line 71
def delete
  locket.unlock
  log.call(at: :delete, args: locket.args, pg_lock: true ) if log
rescue => e
  if log
    log.call(at: :exception, exception: e, pg_lock: true )
  else
    raise e
  end
end
has_lock?()
Alias for: acquired?
lock(&block) click to toggle source

Runs the given block if an advisory lock is able to be acquired.

# File lib/pg_lock.rb, line 44
def lock(&block)
  result = internal_lock(&block)
  return false if result == NO_LOCK
  result
end
lock!(exception_klass = PgLock::UnableToLockError) { |self| ... } click to toggle source

A PgLock::UnableToLock is raised if the lock is not acquired.

# File lib/pg_lock.rb, line 51
def lock!(exception_klass = PgLock::UnableToLockError)
  result = internal_lock { yield self if block_given? }
  if result == NO_LOCK
    raise exception_klass.new(name: name, attempts: max_attempts)
  end
  return result
end

Private Instance Methods

internal_lock(&block) click to toggle source
# File lib/pg_lock.rb, line 93
        def internal_lock(&block)
  if create
    result = nil
    result = Timeout::timeout(ttl, &block) if block_given?
    return_result ? result : true
  else
    return NO_LOCK
  end
ensure
  delete if locket.acquired?
end
key(name) click to toggle source
# File lib/pg_lock.rb, line 115
def key(name)
  i = Zlib.crc32(name.to_s)
  # We need to wrap the value for postgres
  if i > 2147483647
    -(-(i) & 0xffffffff)
  else
    i
  end
end