module Concurrency::ClassMethods
Public Instance Methods
concurrency_cache()
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 19 def concurrency_cache @concurrency_cache ||= ::Rails.cache end
concurrency_cache=(cache)
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 24 def concurrency_cache=(cache) [:read,:write,:delete].each do |method| raise ConcurrencyCacheException, "#{cache} does not implement #{method}" unless cache.respond_to?(method) end @concurrency_cache = cache end
concurrency_safe(*methods)
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 6 def concurrency_safe(*methods) options = methods.extract_options! methods.each do |method| add_concurrency_check(method, options) end end
concurrency_safe_method_locked?(method)
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 14 def concurrency_safe_method_locked?(method) concurrency_cache.read(concurrency_safe_method_cache_name(method)) == 'locked' end
Private Instance Methods
add_concurrency_check(method, options = {})
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 34 def add_concurrency_check(method, options = {}) method_definition = <<-DEFINITION def #{method}_with_concurrency_lock(*args) if concurrency_safe_method_locked?(:#{method}) raise ConcurrentCallException.new(self,:#{method}), "#{self.name}.#{method} is already running" end lock_concurrency_safe_method(:#{method}) return_value = nil begin return_value = #{method}_without_concurrency_lock(*args) ensure unlock_concurrency_safe_method(:#{method}) end return_value end alias_method :#{method}_without_concurrency_lock, :#{method} alias_method :#{method}, :#{method}_with_concurrency_lock DEFINITION if method_type(method, options[:type]) == 'class' method_definition = <<-DEFINITION class << self #{method_definition} end DEFINITION end module_eval method_definition end
class_method?(method)
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 95 def class_method?(method) self.respond_to?(method, true) end
concurrency_safe_method_cache_name(method)
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 75 def concurrency_safe_method_cache_name(method) "#{self.name.underscore}_concurrency_safe_class_method_#{method}" end
instance_method?(method)
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 100 def instance_method?(method) (self.instance_methods + self.private_instance_methods).map(&:to_s).include?(method.to_s) end
lock_concurrency_safe_method(method)
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 65 def lock_concurrency_safe_method(method) concurrency_cache.write(concurrency_safe_method_cache_name(method), 'locked') end
method_type(method, type = nil)
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 80 def method_type(method, type = nil) types = method_types(method, type) raise AmbiguousMethodException.new(self, method), "#{method} for #{self.name} is ambiguous. Please specify the type (instance/class) option" if types.count == 2 raise NoMethodException.new(self, method), "#{method} is not not a valid method for #{self.name}." if types.blank? types.first end
method_types(method, type = nil)
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 88 def method_types(method, type = nil) ['class', 'instance'].select do |mt| (type.blank? || type.to_s == mt) && self.send("#{mt}_method?", method) end end
unlock_concurrency_safe_method(method)
click to toggle source
# File lib/rails_core_extensions/concurrency.rb, line 70 def unlock_concurrency_safe_method(method) concurrency_cache.delete(concurrency_safe_method_cache_name(method)) end