Class: PgLock

Inherits:
Object
  • Object
show all
Defined in:
lib/pg_lock.rb,
lib/pg_lock/locket.rb,
lib/pg_lock/version.rb

Defined Under Namespace

Classes: Locket, UnableToLockError

Constant Summary collapse

PG_LOCK_SPACE =
-2147483648
DEFAULT_CONNECTION_CONNECTOR =
Proc.new do
  if defined?(DEFAULT_CONNECTION)
    DEFAULT_CONNECTION
  elsif defined?(ActiveRecord::Base)
    ActiveRecord::Base.connection.raw_connection
  else
    false
  end
end
DEFAULT_LOGGER =
Proc.new do
  defined?(DEFAULT_LOG) ? DEFAULT_LOG : false
end
UnableToLock =
UnableToLockError
VERSION =
"0.1.2"

Instance Method Summary collapse

Constructor Details

#initialize(name:, attempts: 3, attempt_interval: 1, ttl: 60, connection: DEFAULT_CONNECTION_CONNECTOR.call, log: DEFAULT_LOGGER.call) ⇒ PgLock

Returns a new instance of PgLock.



30
31
32
33
34
35
36
37
38
39
# File 'lib/pg_lock.rb', line 30

def initialize(name:, attempts: 3, attempt_interval: 1, ttl: 60, connection: DEFAULT_CONNECTION_CONNECTOR.call, log: DEFAULT_LOGGER.call )
  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

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

Instance Method Details

#aquired?Boolean Also known as: has_lock?

Returns:

  • (Boolean)


87
88
89
# File 'lib/pg_lock.rb', line 87

def aquired?
  locket.active?
end

#createObject



64
65
66
67
68
69
70
71
72
73
74
# File 'lib/pg_lock.rb', line 64

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

#deleteObject



76
77
78
79
80
81
82
83
84
85
# File 'lib/pg_lock.rb', line 76

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

#lock(&block) ⇒ Object

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



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/pg_lock.rb', line 42

def lock(&block)
  if create
    begin
      Timeout::timeout(ttl, &block) if block_given?
    ensure
      delete
    end
    return true
  else
    return false
  end
end

#lock!(exception_klass = PgLock::UnableToLockError) ⇒ Object

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



56
57
58
59
60
61
62
# File 'lib/pg_lock.rb', line 56

def lock!(exception_klass = PgLock::UnableToLockError)
  if lock { yield self if block_given? }
    # lock successful, do nothing
  else
    raise exception_klass.new(name: name, attempts: max_attempts)
  end
end