Module: ResourceManager

Extended by:
ScLock
Defined in:
lib/apl-library/resource_manager.rb

Defined Under Namespace

Modules: NS, RES

Constant Summary collapse

SERVICE_NAME =
"undef_service"
NAMESPACE =
"APL" + '-' + SERVICE_NAME

Class Method Summary collapse

Class Method Details

.ex_lock(resource, type, client_ref_id, ttl = 300, wait = 200.0, retry_count = 200, &block) ⇒ Object

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)



69
70
71
72
73
74
75
76
77
78
79
80
81
# 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) ⇒ Object

Recursively take locks on all entities before executing original block



84
85
86
87
88
89
90
91
92
93
94
95
96
97
# 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) ⇒ Object

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



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# 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, &block) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
# 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, &block) ⇒ Object

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



52
53
54
55
56
57
58
59
60
61
62
63
64
# 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) ⇒ Object

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



25
26
27
28
29
30
31
32
33
34
35
36
37
# 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) ⇒ Object

Releases lock for a block of entities locked



119
120
121
122
123
124
125
126
127
128
# 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) ⇒ Object



141
142
143
# 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) ⇒ Object



130
131
132
133
134
135
136
137
138
139
# 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