class TransactionalLock::AdvisoryLock
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)
Attributes
name[R]
timeout[R]
Public Class Methods
acquired_locks()
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 18 def acquired_locks acquired_locks_changeable.dup.freeze end
delete_lock(lock)
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 32 def delete_lock(lock) acquired_locks_changeable.delete(lock) end
forget_locks!()
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 36 def forget_locks! @acquired_locks = [] end
new(name, timeout: ::TransactionalLock::Configuration.default_timeout)
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 49 def initialize(name, timeout: ::TransactionalLock::Configuration.default_timeout) @name = name @timeout = timeout @acquired = false end
push_lock(lock)
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 28 def push_lock(lock) acquired_locks_changeable << lock end
release_all_locks()
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 22 def release_all_locks acquired_locks.each do |lock| lock.release end end
Private Class Methods
acquired_locks_changeable()
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 42 def acquired_locks_changeable @acquired_locks ||= [] end
Public Instance Methods
acquire()
click to toggle source
# 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
release()
click to toggle source
# 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
Private Instance Methods
already_locked?()
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 78 def already_locked? self.class.acquired_locks.any? { |lock| lock.name == name } end
raise_on_lock_conflicts!()
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 82 def raise_on_lock_conflicts! conflict_lock = self.class.acquired_locks.detect { |lock| lock.name != name } if conflict_lock raise LockConflict.new self, conflict_lock end end
sql_name()
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 89 def sql_name ActiveRecord::Base.connection.quote_string(@name) end
sql_timeout()
click to toggle source
# File lib/transactional_lock/advisory_lock.rb, line 93 def sql_timeout Integer(@timeout) end