class Mongo::Lock

Constants

VERSION

Attributes

acquired[RW]
configuration[RW]
expires_at[RW]
key[RW]
released[RW]

Public Class Methods

clear_expired(options = {}) click to toggle source
# File lib/mongo-lock.rb, line 57
def self.clear_expired options = {}
  options = configuration.process_collection_options options

  options[:collections].each do |collection|
    configuration.driver.clear_expired collection
  end
end
configuration() click to toggle source
# File lib/mongo-lock.rb, line 43
def self.configuration
  if defined? @@default_configuration
    @@default_configuration
  else
    @@default_configuration = configure
  end
end
configure(options = {}) click to toggle source
# File lib/mongo-lock.rb, line 29
def self.configure options = {}, &block
  defaults = {
    timeout_in: false,
    limit: 100,
    frequency: 1,
    expire_in: 10,
    should_raise: false,
    driver: options[:driver] || (require('mongo-lock/drivers/mongo') && ::Mongo::Lock::Drivers::Mongo),
    owner: Proc.new { "#{`hostname`.strip}:#{Process.pid}:#{Thread.object_id}" }
  }
  defaults = defaults.merge(@@default_configuration) if defined?(@@default_configuration) && @@default_configuration
  @@default_configuration = Configuration.new(defaults, options, &block)
end
ensure_indexes() click to toggle source
# File lib/mongo-lock.rb, line 51
def self.ensure_indexes
  configuration.collections.each_pair do |key, collection|
    configuration.driver.ensure_indexes collection
  end
end
new(key, options = {}) click to toggle source
# File lib/mongo-lock.rb, line 73
def initialize key, options = {}
  self.configuration = Configuration.new self.class.configuration.to_hash, options
  self.key = retrieve_lock_key key
  acquire_if_acquired
end
release_all(options = {}) click to toggle source
# File lib/mongo-lock.rb, line 65
def self.release_all options = {}
  options = configuration.process_collection_options options

  options[:collections].each do |collection|
    configuration.driver.release_collection collection, options[:owner]
  end
end

Public Instance Methods

acquire(options = {}) click to toggle source
# File lib/mongo-lock.rb, line 86
def acquire options = {}, &block
  options = inherit_options options
  i = 1
  time_spent = 0

  loop do
    result = try_acquire options, i, time_spent, &block
    return result unless result.nil?

    frequency = call_if_proc options[:frequency], i
    sleep frequency
    time_spent += frequency
    i += 1
  end
end
acquire_if_acquired() click to toggle source
# File lib/mongo-lock.rb, line 217
def acquire_if_acquired
  self.acquired = true if driver.is_acquired?
end
acquired?() click to toggle source

Current state

# File lib/mongo-lock.rb, line 191
def acquired?
  !!acquired && !expired?
end
available?(options = {}) click to toggle source
# File lib/mongo-lock.rb, line 183
def available? options = {}
  options = inherit_options options
  existing_lock = driver.find_existing
  !existing_lock || existing_lock['owner'] == options[:owner]
end
call_block(options) { |self| ... } click to toggle source
# File lib/mongo-lock.rb, line 128
def call_block options, &block
  if block_given?
    yield self
    release(options)
  end
  true
end
call_if_proc(proc, *args) click to toggle source
# File lib/mongo-lock.rb, line 230
def call_if_proc proc, *args
  if proc.is_a? Proc
    proc.call(*args)
  else
    proc
  end
end
configure(options = {}) { |configuration| ... } click to toggle source

API

# File lib/mongo-lock.rb, line 81
def configure options = {}, &block
  self.configuration = Configuration.new self.configuration.to_hash, options
  yield self.configuration if block_given?
end
driver() click to toggle source

Utils

# File lib/mongo-lock.rb, line 205
def driver
  @driver ||= configuration.driver.new self
end
expired?() click to toggle source
# File lib/mongo-lock.rb, line 195
def expired?
  !!(expires_at && expires_at < Time.now)
end
extend(options = {}) click to toggle source
# File lib/mongo-lock.rb, line 178
def extend options = {}
  time = configuration.to_hash.merge(options)[:expire_in]
  extend_by time, options
end
extend_by(time, options = {}) click to toggle source
# File lib/mongo-lock.rb, line 165
def extend_by time, options = {}
  options = inherit_options options

  # Can't extend a lock that hasn't been acquired or expired
  if !acquired? || expired?
    return raise_or_false options, NotExtendedError

  else
    driver.find_and_update time, options
    true
  end
end
inherit_options(options) click to toggle source
# File lib/mongo-lock.rb, line 226
def inherit_options options
  configuration.to_hash.merge options
end
raise_or_false(options, error = NotAcquiredError) click to toggle source
# File lib/mongo-lock.rb, line 221
def raise_or_false options, error = NotAcquiredError
  raise error if options[:should_raise]
  false
end
release(options = {}) click to toggle source
# File lib/mongo-lock.rb, line 136
def release options = {}
  options = inherit_options options

  # If the lock has already been released
  if released?
    return true

  # If the lock has expired its as good as released
  elsif expired?
    self.released = true
    self.acquired = false
    return true

  # We must have acquired the lock to release it
  elsif !acquired?
    if acquire options.merge(should_raise: false)
      return release options
    else
      return raise_or_false options, NotReleasedError
    end

  else
    self.released = true
    self.acquired = false
    driver.remove options
    return true
  end
end
released?() click to toggle source
# File lib/mongo-lock.rb, line 199
def released?
  !!released
end
retrieve_lock_key(key) click to toggle source
# File lib/mongo-lock.rb, line 209
def retrieve_lock_key key
  case
  when key.respond_to?(:lock_key)  then key.lock_key
  when key.is_a?(Array)            then key.map { |element| retrieve_lock_key(element) }.to_param
  else                                  key.to_param
  end.to_s
end
try_acquire(options, i, time_spent, &block) click to toggle source
# File lib/mongo-lock.rb, line 102
def try_acquire options, i, time_spent, &block

  # If timeout has expired
  if options[:timeout_in] && options[:timeout_in] < time_spent
    return raise_or_false options

  # If limit has expired
  elsif options[:limit] && options[:limit] < i
    return raise_or_false options

  # If there is an existing lock
  elsif existing_lock = driver.find_or_insert(options)
    # If the lock is owned by me
    if existing_lock['owner'] == options[:owner]
      self.acquired = true
      extend_by options[:expire_in]
      return true
    end

  # If the lock was acquired
  else
    self.acquired = true
    return call_block options, &block
  end
end