class DynaModel::Extensions::Lock
Constants
- HOST
Public Class Methods
acquire(lock_name, options={})
click to toggle source
# File lib/dyna_model/extensions/lock.rb, line 43 def self.acquire(lock_name, options={}) options[:acquisition_timeout] ||= 15 options[:expires_in] ||= 10 retries = 0 begin Timeout::timeout(options[:acquisition_timeout]) do begin locked_at = DateTime.now expires_at = locked_at + options[:expires_in].seconds lock_obj = self.new( lock_name: lock_name, locked_at: locked_at, expires_at: expires_at, locked_by: self.locked_by ) if lock_obj.save(expected: { :locked_by.null => "", :expires_at.le => locked_at }, conditional_operator: :or) DynaModel::Config.logger.info "Acquired lock '#{lock_name}'" lock_obj else raise "Error acquiring lock: #{lock_obj.errors.full_messages.to_sentence}" end rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException DynaModel::Config.logger.info "Lock condition failed for '#{lock_name}'. Retrying..." sleep((2 ** retries) * 0.05) retries += 1 retry end end rescue Timeout::Error raise LockNotAcquired, "Could not acquire lock after #{options[:acquisition_timeout]} seconds" end end
extend(lock_name, extension_time=5.seconds)
click to toggle source
# File lib/dyna_model/extensions/lock.rb, line 100 def self.extend(lock_name, extension_time=5.seconds) locked_at = DateTime.now expires_at = locked_at + extension_time lock_obj = self.new( lock_name: lock_name, locked_at: locked_at, expires_at: expires_at, locked_by: self.locked_by ) if lock_obj.save(expected: { :locked_by.eq => self.locked_by }) DynaModel::Config.logger.info "Extended lock '#{lock_name}' for #{extension_time} seconds" true else raise "Error extending lock: #{lock_obj.errors.full_messages.to_sentence}" end rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException => e DynaModel::Config.logger.info "Condition failed to extend lock '#{lock_name}'" end
lock(lock_name, options={}, &block)
click to toggle source
# File lib/dyna_model/extensions/lock.rb, line 28 def self.lock(lock_name, options={}, &block) lock_acquired = false if lock_obj_acquired = self.acquire(lock_name, options) lock_acquired = true if block begin result = (block.arity == 1) ? block.call(lock_obj_acquired) : block.call ensure release(lock_name) if lock_acquired end end result end end
locked_by()
click to toggle source
# File lib/dyna_model/extensions/lock.rb, line 24 def self.locked_by "#{HOST}:#{Process.pid}" end
release(lock_name, options={})
click to toggle source
# File lib/dyna_model/extensions/lock.rb, line 80 def self.release(lock_name, options={}) lock_obj = self.new( lock_name: lock_name, locked_at: nil, expires_at: nil, locked_by: nil ) if lock_obj.save(expected: { :locked_by.eq => self.locked_by }) DynaModel::Config.logger.info "Released lock '#{lock_name}'" true else raise "Error releasing lock: #{lock_obj.errors.full_messages.to_sentence}" end rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException => e DynaModel::Config.logger.info "Condition failed to release lock '#{lock_name}'" end