Class: TransactionalLock::AdvisoryLock

Inherits:
Object
  • Object
show all
Defined in:
lib/transactional_lock/advisory_lock.rb

Overview

Represents a database advisory lock. N.B. currently quite MySQL specific, except that its interface allows more than one active lock MySQL will only ever support one lock at a time (releasing earlier locks implicitly)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, timeout: ::TransactionalLock::Configuration.default_timeout) ⇒ AdvisoryLock

Returns a new instance of AdvisoryLock.



49
50
51
52
53
# File 'lib/transactional_lock/advisory_lock.rb', line 49

def initialize(name, timeout: ::TransactionalLock::Configuration.default_timeout)
  @name = name
  @timeout = timeout
  @acquired = false
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



47
48
49
# File 'lib/transactional_lock/advisory_lock.rb', line 47

def name
  @name
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



47
48
49
# File 'lib/transactional_lock/advisory_lock.rb', line 47

def timeout
  @timeout
end

Class Method Details

.acquired_locksObject



18
19
20
# File 'lib/transactional_lock/advisory_lock.rb', line 18

def acquired_locks
  acquired_locks_changeable.dup.freeze
end

.delete_lock(lock) ⇒ Object



32
33
34
# File 'lib/transactional_lock/advisory_lock.rb', line 32

def delete_lock(lock)
  acquired_locks_changeable.delete(lock)
end

.forget_locks!Object



36
37
38
# File 'lib/transactional_lock/advisory_lock.rb', line 36

def forget_locks!
  @acquired_locks = []
end

.push_lock(lock) ⇒ Object



28
29
30
# File 'lib/transactional_lock/advisory_lock.rb', line 28

def push_lock(lock)
  acquired_locks_changeable << lock
end

.release_all_locksObject



22
23
24
25
26
# File 'lib/transactional_lock/advisory_lock.rb', line 22

def release_all_locks
  acquired_locks.each do |lock|
    lock.release
  end
end

Instance Method Details

#acquireObject



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/transactional_lock/advisory_lock.rb', line 55

def acquire
  return if already_locked?
  raise_on_lock_conflicts!

  result = ActiveRecord::Base.connection.execute(
             "SELECT GET_LOCK('#{sql_name}', #{sql_timeout})")

  unless result.first.first == 1
    raise LockAcquireError.new "Could not acquire lock '#{@name}'."
  end

  self.class.push_lock(self)
end

#releaseObject



69
70
71
72
73
74
# File 'lib/transactional_lock/advisory_lock.rb', line 69

def release
  ActiveRecord::Base.connection.execute("SELECT RELEASE_LOCK('#{sql_name}')")
ensure
  # In any case consider this lock being released (avoiding inability for new acquires)
  self.class.delete_lock(self)
end