robust-redis-lock 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/redis-lock.rb +52 -15
- data/lib/robust-redis-lock/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23f3a1cbf8593c30a609665262248cc8359727ba
|
4
|
+
data.tar.gz: 3aff7aaaca003505cf84213eef01421ab98eef32
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ceb8ffe2f1b2885cae20a2c586e82fc1e1fd9e4ba2956cf50b024f62a51ade42f6649a419924fe8f12c2d48d2aa4c1447c1f096294754c70acbc6e35ad1ed3d3
|
7
|
+
data.tar.gz: 62a08c7e3bdd4ce2b765128f79d71ee2d70df13120a70cc554102492770ef647dcefe05807329458f17121d61c8853fc6aa12607fd4ff43bce774cc21501239c
|
data/lib/redis-lock.rb
CHANGED
@@ -19,7 +19,20 @@ class Redis::Lock
|
|
19
19
|
redis = options[:redis] || self.redis
|
20
20
|
raise "redis cannot be nil" if redis.nil?
|
21
21
|
|
22
|
-
redis.zrangebyscore(key_group_key(options), 0, Time.now.to_i).to_a.map
|
22
|
+
redis.zrangebyscore(key_group_key(options), 0, Time.now.to_i).to_a.map do |key_token|
|
23
|
+
key, token = key_token.scan(/(.*):(.*)$/).first
|
24
|
+
self.new(key, options.merge(:token => token))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def all(options={})
|
29
|
+
redis = options[:redis] || self.redis
|
30
|
+
raise "redis cannot be nil" if redis.nil?
|
31
|
+
|
32
|
+
redis.zrangebyscore(key_group_key(options), 0, "+inf").to_a.map do |key_token|
|
33
|
+
key, token = key_token.scan(/(.*):(.*)$/).first
|
34
|
+
self.new(key, options.merge(:token => token))
|
35
|
+
end
|
23
36
|
end
|
24
37
|
|
25
38
|
def key_group_key(options)
|
@@ -44,6 +57,7 @@ class Redis::Lock
|
|
44
57
|
@timeout = @options[:timeout] || self.class.timeout
|
45
58
|
@expire = @options[:expire] || self.class.expire
|
46
59
|
@sleep = @options[:sleep] || self.class.sleep
|
60
|
+
@token = @options[:token]
|
47
61
|
end
|
48
62
|
|
49
63
|
def synchronize(&block)
|
@@ -54,6 +68,7 @@ class Redis::Lock
|
|
54
68
|
try_unlock
|
55
69
|
end
|
56
70
|
rescue Recovered
|
71
|
+
block.call
|
57
72
|
end
|
58
73
|
|
59
74
|
def lock(options={})
|
@@ -91,18 +106,22 @@ class Redis::Lock
|
|
91
106
|
local next_token = redis.call('incr', token_key)
|
92
107
|
|
93
108
|
redis.call('hset', key, 'expires_at', expires_at)
|
94
|
-
redis.call('
|
95
|
-
redis.call('zadd', key_group, expires_at, bare_key)
|
109
|
+
redis.call('zadd', key_group, expires_at, bare_key .. ':' .. next_token)
|
96
110
|
|
111
|
+
local return_value = nil
|
97
112
|
if prev_expires_at then
|
98
|
-
|
113
|
+
redis.call('zrem', key_group, bare_key .. ':' .. redis.call('hget', key, 'token'))
|
114
|
+
return_value = {'recovered', next_token, redis.call('hget', key, 'recovery_data')}
|
99
115
|
else
|
100
116
|
redis.call('hset', key, 'recovery_data', recovery_data)
|
101
|
-
|
117
|
+
return_value = {'acquired', next_token, nil}
|
102
118
|
end
|
119
|
+
|
120
|
+
redis.call('hset', key, 'token', next_token)
|
121
|
+
return return_value
|
103
122
|
LUA
|
104
123
|
result, token, recovery_data = @@lock_script.eval(@redis,
|
105
|
-
:keys => [
|
124
|
+
:keys => [namespaced_key, @key_group_key],
|
106
125
|
:argv => [@key, now.to_i, now.to_i + @expire, options[:recovery_data]])
|
107
126
|
|
108
127
|
case result
|
@@ -134,13 +153,13 @@ class Redis::Lock
|
|
134
153
|
|
135
154
|
if redis.call('hget', key, 'token') == token then
|
136
155
|
redis.call('del', key)
|
137
|
-
redis.call('zrem', key_group, bare_key)
|
156
|
+
redis.call('zrem', key_group, bare_key .. ':' .. token)
|
138
157
|
return true
|
139
158
|
else
|
140
159
|
return false
|
141
160
|
end
|
142
161
|
LUA
|
143
|
-
!!@@unlock_script.eval(@redis, :keys => [
|
162
|
+
!!@@unlock_script.eval(@redis, :keys => [namespaced_key, @key_group_key], :argv => [@key, @token])
|
144
163
|
end
|
145
164
|
|
146
165
|
def extend
|
@@ -154,16 +173,30 @@ class Redis::Lock
|
|
154
173
|
local bare_key = ARGV[1]
|
155
174
|
local expires_at = tonumber(ARGV[2])
|
156
175
|
local token = ARGV[3]
|
176
|
+
local token_key = 'redis:lock:token'
|
157
177
|
|
158
178
|
if redis.call('hget', key, 'token') == token then
|
179
|
+
local next_token = redis.call('incr', token_key)
|
180
|
+
|
159
181
|
redis.call('hset', key, 'expires_at', expires_at)
|
160
|
-
redis.call('
|
161
|
-
|
182
|
+
redis.call('hset', key, 'token', next_token)
|
183
|
+
|
184
|
+
redis.call('zrem', key_group, bare_key .. ':' .. token)
|
185
|
+
redis.call('zadd', key_group, expires_at, bare_key .. ':' .. next_token)
|
186
|
+
|
187
|
+
return { next_token, redis.call('hget', key, 'recovery_data') }
|
162
188
|
else
|
163
189
|
return false
|
164
190
|
end
|
165
191
|
LUA
|
166
|
-
|
192
|
+
result = @@extend_script.eval(@redis, :keys => [namespaced_key, @key_group_key], :argv => [@key, now.to_i + @expire, @token])
|
193
|
+
|
194
|
+
if result
|
195
|
+
@token, @recovery_data = result
|
196
|
+
true
|
197
|
+
else
|
198
|
+
false
|
199
|
+
end
|
167
200
|
end
|
168
201
|
|
169
202
|
def now
|
@@ -178,7 +211,11 @@ class Redis::Lock
|
|
178
211
|
@key
|
179
212
|
end
|
180
213
|
|
181
|
-
|
214
|
+
def namespaced_key
|
215
|
+
NAMESPACE + ':' + @key
|
216
|
+
end
|
217
|
+
|
218
|
+
class Error < RuntimeError
|
182
219
|
attr_reader :lock
|
183
220
|
|
184
221
|
def initialize(lock)
|
@@ -186,19 +223,19 @@ class Redis::Lock
|
|
186
223
|
end
|
187
224
|
end
|
188
225
|
|
189
|
-
class LostLock <
|
226
|
+
class LostLock < Error
|
190
227
|
def message
|
191
228
|
"The following lock was lost while trying to modify: #{@lock}"
|
192
229
|
end
|
193
230
|
end
|
194
231
|
|
195
|
-
class
|
232
|
+
class Recovered < Error
|
196
233
|
def message
|
197
234
|
"The following lock was recovered: #{@lock}"
|
198
235
|
end
|
199
236
|
end
|
200
237
|
|
201
|
-
class
|
238
|
+
class Timeout < Error
|
202
239
|
def message
|
203
240
|
"The following lock timed-out waiting to get aquired: #{@lock}"
|
204
241
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: robust-redis-lock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kareem Kouddous
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -54,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
54
|
version: '0'
|
55
55
|
requirements: []
|
56
56
|
rubyforge_project:
|
57
|
-
rubygems_version: 2.2.
|
57
|
+
rubygems_version: 2.2.2
|
58
58
|
signing_key:
|
59
59
|
specification_version: 4
|
60
60
|
summary: Robust redis lock
|