From d2a455a55ad55c07365bf86f48868f0e055c3d7e Mon Sep 17 00:00:00 2001 From: Matthew Spence Date: Wed, 23 Apr 2014 19:59:39 +0100 Subject: [PATCH] Pulled out some functionality into distinct modules --- lib/mongo-lock.rb | 119 ++---------------- lib/mongo-lock/acquisition.rb | 53 ++++++++ ...ence_methods.rb => convenience_methods.rb} | 2 +- lib/mongo-lock/extension.rb | 25 ++++ lib/mongo-lock/release.rb | 46 +++++++ ...th_raise_methods.rb => send_with_raise.rb} | 2 +- 6 files changed, 136 insertions(+), 111 deletions(-) create mode 100644 lib/mongo-lock/acquisition.rb rename lib/mongo-lock/{class_convenience_methods.rb => convenience_methods.rb} (95%) create mode 100644 lib/mongo-lock/extension.rb create mode 100644 lib/mongo-lock/release.rb rename lib/mongo-lock/{send_with_raise_methods.rb => send_with_raise.rb} (94%) diff --git a/lib/mongo-lock.rb b/lib/mongo-lock.rb index 72dc0c6..23a43a1 100644 --- a/lib/mongo-lock.rb +++ b/lib/mongo-lock.rb @@ -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) @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/lib/mongo-lock/acquisition.rb b/lib/mongo-lock/acquisition.rb new file mode 100644 index 0000000..91098eb --- /dev/null +++ b/lib/mongo-lock/acquisition.rb @@ -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 diff --git a/lib/mongo-lock/class_convenience_methods.rb b/lib/mongo-lock/convenience_methods.rb similarity index 95% rename from lib/mongo-lock/class_convenience_methods.rb rename to lib/mongo-lock/convenience_methods.rb index fc67846..8fb1c62 100644 --- a/lib/mongo-lock/class_convenience_methods.rb +++ b/lib/mongo-lock/convenience_methods.rb @@ -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) diff --git a/lib/mongo-lock/extension.rb b/lib/mongo-lock/extension.rb new file mode 100644 index 0000000..1a0fb49 --- /dev/null +++ b/lib/mongo-lock/extension.rb @@ -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 diff --git a/lib/mongo-lock/release.rb b/lib/mongo-lock/release.rb new file mode 100644 index 0000000..a683ba5 --- /dev/null +++ b/lib/mongo-lock/release.rb @@ -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 diff --git a/lib/mongo-lock/send_with_raise_methods.rb b/lib/mongo-lock/send_with_raise.rb similarity index 94% rename from lib/mongo-lock/send_with_raise_methods.rb rename to lib/mongo-lock/send_with_raise.rb index a499bf2..1bb5575 100644 --- a/lib/mongo-lock/send_with_raise_methods.rb +++ b/lib/mongo-lock/send_with_raise.rb @@ -1,6 +1,6 @@ module Mongo class Lock - module SendWithRaiseMethods + module SendWithRaise def send_with_raise method, *args args.last[:should_raise] = true