module ResourceManager

Constants

NAMESPACE
SERVICE_NAME

Public Class Methods

ex_lock(resource, type, client_ref_id, ttl=300, wait=200.0, retry_count=200, &block) click to toggle source

Supposed to be used as a common method across all services for exclusive locking of accounting entities. Supposed to be used for short duration hence lots of quick retries ( 100 each spanning 200ms)

# File lib/apl-library/resource_manager.rb, line 69
def self.ex_lock resource, type, client_ref_id, ttl=300, wait=200.0, retry_count=200, &block
  # resource is an accounting entity
  unless (RES.constants.map { |c| RES.const_get(c)}).include? resource
    raise InvalidDataError.new(:message => "Invalid resource locked: #{resource}")
  end

  # so that everything is in naagin case
  type = type.to_s.underscore
  client_ref_id = client_ref_id.to_s
  key = type + "-" + client_ref_id

  lock(NS::EXCLUSIVE, resource, { :key => key }, nil, ttl, wait, retry_count, &block)
end
ex_lock_all(resource_type_crids, ttl=300, wait=200.0, retry_count=20, &block) click to toggle source

Recursively take locks on all entities before executing original block

# File lib/apl-library/resource_manager.rb, line 84
def self.ex_lock_all resource_type_crids, ttl=300, wait=200.0, retry_count=20, &block
  resource, type, client_ref_id = resource_type_crids.shift

  if resource_type_crids.size == 0
    ex_lock resource, type, client_ref_id, ttl, wait, retry_count, &block
    return
  end

  new_block =  Proc.new do
    ex_lock_all resource_type_crids, ttl, wait, retry_count, &block
  end

  ex_lock resource, type, client_ref_id, ttl, wait, retry_count, &new_block
end
lock_for_each(name_space, resource_name, entities, key_name=:id, expiry=nil) click to toggle source

Tries to lock on possible entities given and returns the list of entities for which it was able to acquire lock on

# File lib/apl-library/resource_manager.rb, line 101
def self.lock_for_each name_space, resource_name, entities, key_name=:id, expiry=nil
  reserved_entities = []
  entities.each do |entity|
    begin
      expiry = 24 * 60 * 60 if expiry.nil? # Acquire lock for a day by default
      lock(name_space, resource_name, {resource_name.to_sym => entity[key_name]}, nil, expiry)
      reserved_entities << entity

      # TODO Need to check with platform team (This is hack to get off re-entrant locks)
      remove_caller_key("#{name_space}-#{resource_name}", {resource_name.to_sym => entity[key_name]}.sort.to_s)
    rescue ScLock::LockNotAvailable => le
      logger.info("Skipped entity : #{entity}, as unable to get lock on it, Error: #{le.message}")
    end
  end
  reserved_entities
end
lock_resource(resource_name, lock_params, time_to_live=300, retry_count = 5, lock_wait = 1000) { || ... } click to toggle source
# File lib/apl-library/resource_manager.rb, line 39
def self.lock_resource(resource_name, lock_params, time_to_live=300, retry_count = 5, lock_wait = 1000, &block)
  begin
    return_value = nil
    lock(NAMESPACE, resource_name, lock_params, nil, time_to_live, lock_wait, retry_count) do
      return_value = yield
    end
    return_value
  rescue ScLock::LockNotAvailable
    raise ResourceLockedError.new
  end
end
lock_resources(resource_name, lock_param_array, time_to_live=300, retry_count=5) { || ... } click to toggle source

Tries to lock on a block of objects -> if 1 fails the whole block fails

# File lib/apl-library/resource_manager.rb, line 52
def self.lock_resources(resource_name, lock_param_array, time_to_live=300, retry_count=5, &block)
  if lock_param_array.empty?
    return
  elsif (lock_param_array.size == 1)
    ResourceManager.lock_resource(resource_name, lock_param_array.pop, time_to_live, retry_count) do
      yield if block
    end
  else
    ResourceManager.lock_resource(resource_name, lock_param_array.pop, time_to_live, retry_count) do
      lock_resources(resource_name, lock_param_array, time_to_live, retry_count, &block)
    end
  end
end
locked_block(namespace, resource, params, wait_time=1000.0, retry_count=0, &block) click to toggle source

hold lock only for the 'block' and delete from database once done.

# File lib/apl-library/resource_manager.rb, line 25
def self.locked_block namespace, resource, params, wait_time=1000.0, retry_count=0, &block
  error = nil
  begin
    lock(namespace, resource, params, nil, 600, wait_time, retry_count, &block)
  rescue Exception => e
    error = e
    # delete lock and raise it again
    resource_lock = ScLock::Lock.find_by_resource_name_and_key("#{namespace}-#{resource}", params.sort.to_s)
    resource_lock.delete if resource_lock
  end

  raise error if error
end
release_for_all(name_space, resource_name, entities, key_name=:id) click to toggle source

Releases lock for a block of entities locked

# File lib/apl-library/resource_manager.rb, line 119
def self.release_for_all name_space, resource_name, entities, key_name=:id
  entities.each do |entity|
    lock_on_resource = ScLock::Lock.find_by_resource_name_and_key("#{name_space}-#{resource_name}", {resource_name.to_sym => entity[key_name]}.sort.to_s)
    if lock_on_resource.blank?
      logger.error "Unable to release the lock, No lock found on resource #{entity[key_name]}"
      next
    end
    lock_on_resource.delete
  end
end
remove_caller_key(resource_name, key) click to toggle source
# File lib/apl-library/resource_manager.rb, line 141
def self.remove_caller_key(resource_name, key)
  Thread.current[:locks].delete({resource_name => resource_name, :key => key}) if Thread.current[:locks]
end
update_expiry_date_for_all(name_space, resource_name, entities, expiry_date_time, key_name=:id) click to toggle source
# File lib/apl-library/resource_manager.rb, line 130
def self.update_expiry_date_for_all name_space, resource_name, entities, expiry_date_time, key_name=:id
  entities.each do |entity|
    lock_on_resource = ScLock::Lock.find_by_resource_name_and_key("#{name_space}-#{resource_name}", {resource_name.to_sym => entity[key_name]}.sort.to_s)
    if lock_on_resource.blank?
      logger.error "Unable to update the expiry date of lock, No lock found on resource #{entity[key_name]}"
      next
    end
    lock_on_resource.update_attribute(:lock_expiry_time, expiry_date_time)
  end
end