Class: Pesto::Lock
- Inherits:
-
Object
- Object
- Pesto::Lock
- Defined in:
- lib/pesto/lock.rb
Instance Method Summary collapse
- #conf ⇒ Object
- #cp ⇒ Object
- #get_locks(names, opts = {}) ⇒ Object
-
#initialize(ctx = {}, opts = {}) ⇒ Lock
constructor
A new instance of Lock.
- #load_scripts ⇒ Object
- #lock(_names, _opts = {}) ⇒ Object
- #locki(name = 'global', opts = {}) ⇒ Object
- #lockx(name = 'global', opts = {}, err = 'ERR_LOCKING') ⇒ Object
- #merge_options(o = {}, *filter) ⇒ Object
- #unlock(_names = []) ⇒ Object
Constructor Details
#initialize(ctx = {}, opts = {}) ⇒ Lock
Returns a new instance of Lock.
4 5 6 7 8 9 10 11 12 13 14 15 16 |
# File 'lib/pesto/lock.rb', line 4 def initialize(ctx = {}, opts = {}) @ctx = ctx raise 'ERR_REDIS_NOTFOUND' if @ctx[:pool].nil? @conf = { :timeout_lock_expire => 5, :timeout_lock => 1, :interval_check => 0.05 }.merge(opts) load_scripts end |
Instance Method Details
#conf ⇒ Object
39 40 41 |
# File 'lib/pesto/lock.rb', line 39 def conf @conf end |
#cp ⇒ Object
43 44 45 |
# File 'lib/pesto/lock.rb', line 43 def cp @ctx[:pool] end |
#get_locks(names, opts = {}) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/pesto/lock.rb', line 77 def get_locks names, opts = {} locked = 0 locks = [] res = [] timeout_lock_expire = opts[:timeout_lock_expire] cp.with do |rc| res = rc.multi do names.each do |n| res << rc.evalsha(@script_sha, { :keys => [lock_hash(n)], :argv => [timeout_lock_expire] }) end end end names.each_with_index do |n, ix| next if res[ix] != 1 locked += 1 locks.push n end return [res, locks, locked == names.size] end |
#load_scripts ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/pesto/lock.rb', line 18 def load_scripts cp.with do |rc| @script_sha = rc.script( :load, "local ret = 0 \ local timeout = tonumber(ARGV[1]) \ if type(timeout) ~= 'number' then \ return 0 \ end \ local res = redis.call('setnx', KEYS[1], 1) \ if res == 1 then \ redis.call('expire', KEYS[1], ARGV[1]) \ ret = 1 \ else \ ret = 0 \ end \ return ret" ) end end |
#lock(_names, _opts = {}) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/pesto/lock.rb', line 53 def lock _names, _opts = {} opts = _opts, :timeout_lock_expire, :timeout_lock, :interval_check names = (_names.is_a?(String) ? [_names] : _names).uniq opts[:timeout_lock_expire] = opts[:timeout_lock_expire].to_i opts[:timeout_lock_expire] += (opts[:timeout_lock] * names.size).ceil.to_i t_start = Time.now stop = false while true res, locks, stop = get_locks names, { :timeout_lock_expire => opts[:timeout_lock_expire] } break if stop || (Time.now - t_start) > opts[:timeout_lock] unlock locks sleep opts[:interval_check] end stop ? 1 : 0 end |
#locki(name = 'global', opts = {}) ⇒ Object
104 105 106 |
# File 'lib/pesto/lock.rb', line 104 def locki name = 'global', opts = {} lock name, opts.merge(timeout_lock: 0) end |
#lockx(name = 'global', opts = {}, err = 'ERR_LOCKING') ⇒ Object
108 109 110 111 112 113 |
# File 'lib/pesto/lock.rb', line 108 def lockx name = 'global', opts = {}, err = 'ERR_LOCKING' locked = lock(name, opts) return 1 if locked == 1 raise "#{err} (#{name})" end |
#merge_options(o = {}, *filter) ⇒ Object
47 48 49 50 51 |
# File 'lib/pesto/lock.rb', line 47 def o = {}, *filter c = conf.merge(o) c.delete_if{|k,v| !filter.include?(k) } unless filter.empty? c end |
#unlock(_names = []) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/pesto/lock.rb', line 115 def unlock _names = [] _names = [_names] if _names.is_a?(String) names = _names.uniq res = [] cp.with do |rc| res = rc.multi do names.each do |n| rc.del(lock_hash(n)) end end end val = res.reduce(0){|sum, n| sum + n} val > 0 ? 1 : 0 end |