Skip to content

Commit

Permalink
Pulled out some functionality into distinct modules
Browse files Browse the repository at this point in the history
  • Loading branch information
msaspence committed Apr 23, 2014
1 parent 35afb83 commit d2a455a
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 111 deletions.
119 changes: 10 additions & 109 deletions lib/mongo-lock.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
require 'mongo-lock/configuration'
require 'mongo-lock/drivers/base'
require 'mongo-lock/class_convenience_methods'
require 'mongo-lock/send_with_raise_methods'
require 'mongo-lock/convenience_methods'
require 'mongo-lock/send_with_raise'
require 'mongo-lock/acquisition'
require 'mongo-lock/release'
require 'mongo-lock/extension'

# If we are using Rails then we will include the Mongo::Lock railtie.
if defined?(Rails)
Expand All @@ -11,8 +14,11 @@
module Mongo
class Lock

extend Mongo::Lock::ClassConvenienceMethods
include Mongo::Lock::SendWithRaiseMethods
extend Mongo::Lock::ConvenienceMethods
include Mongo::Lock::SendWithRaise
include Mongo::Lock::Acquisition
include Mongo::Lock::Release
include Mongo::Lock::Extension

class NotAcquiredError < StandardError ; end
class NotReleasedError < StandardError ; end
Expand Down Expand Up @@ -62,69 +68,17 @@ def self.clear_expired options = {}
end
end

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

def initialize key, options = {}
self.configuration = Configuration.new self.class.configuration.to_hash, options
self.key = retrieve_lock_key key
acquire_if_acquired
end

# API

def configure options = {}, &block
self.configuration = Configuration.new self.configuration.to_hash, options
yield self.configuration if block_given?
end

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

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

def call_block options, &block
if block_given?
yield self
Expand All @@ -133,61 +87,12 @@ def call_block options, &block
true
end

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

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

def extend options = {}
time = configuration.to_hash.merge(options)[:expire_in]
extend_by time, options
end

def available? options = {}
options = inherit_options options
existing_lock = driver.find_existing
!existing_lock || existing_lock['owner'] == options[:owner]
end

# Current state

def acquired?
!!acquired && !expired?
end
Expand All @@ -214,10 +119,6 @@ def retrieve_lock_key key
end.to_s
end

def acquire_if_acquired
self.acquired = true if driver.is_acquired?
end

def raise_or_false options, error = NotAcquiredError
raise error if options[:should_raise]
false
Expand Down
53 changes: 53 additions & 0 deletions lib/mongo-lock/acquisition.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module Mongo
class Lock
module Acquisition

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

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

def acquire_if_acquired
self.acquired = true if driver.is_acquired?
end

end
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Mongo
class Lock
module ClassConvenienceMethods
module ConvenienceMethods

def init_and_send key, options = {}, method, &block
lock = Mongo::Lock.new(key, options)
Expand Down
25 changes: 25 additions & 0 deletions lib/mongo-lock/extension.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module Mongo
class Lock
module Extension

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

def extend options = {}
time = configuration.to_hash.merge(options)[:expire_in]
extend_by time, options
end

end
end
end
46 changes: 46 additions & 0 deletions lib/mongo-lock/release.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module Mongo
class Lock
module Release

def self.included base
def base.release_all options = {}
options = configuration.process_collection_options options

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

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

end
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Mongo
class Lock
module SendWithRaiseMethods
module SendWithRaise

def send_with_raise method, *args
args.last[:should_raise] = true
Expand Down

0 comments on commit d2a455a

Please sign in to comment.