redlock 0.1.6 → 0.1.7
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/.travis.yml +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +16 -0
- data/lib/redlock/client.rb +42 -0
- data/lib/redlock/version.rb +1 -1
- data/spec/client_spec.rb +34 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86073e680a1deb905852ddfcd28042cf81729875
|
4
|
+
data.tar.gz: 76cffc3d01b4fa649ad4ae4276149453282c0ed4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b0687bd912eff82bb3f4607de313d681d1e18971cbd3b6b484bae0fabae38b258ef423f0c00256b45e633fbc83abea9b38c57fbf08ce4d6567a2c254701eeb7
|
7
|
+
data.tar.gz: 86dc485ebc704b9d46bd6878d18f9b7403c13840721a2475b4b61b5c7b4099a40db3375045df8c8be7e9270d52f9560854b489a3656805046d995e253b1d126b
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -95,6 +95,22 @@ rescue Redlock::LockError
|
|
95
95
|
end
|
96
96
|
```
|
97
97
|
|
98
|
+
To extend the life of the lock, provided that you didn't let it expire:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
begin
|
102
|
+
block_result = lock_manager.lock!("resource_key", 2000) do |lock_info|
|
103
|
+
# critical code
|
104
|
+
lock_manager.extend_life!(lock_info, 3000)
|
105
|
+
# more critical code
|
106
|
+
end
|
107
|
+
rescue Redlock::LockError
|
108
|
+
# error handling
|
109
|
+
end
|
110
|
+
```
|
111
|
+
There's also a non-bang version that returns true when the lock was
|
112
|
+
extended
|
113
|
+
|
98
114
|
## Run tests
|
99
115
|
|
100
116
|
Make sure you have at least 1 redis instances up.
|
data/lib/redlock/client.rb
CHANGED
@@ -52,6 +52,30 @@ module Redlock
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
def extend_life(to_extend, ttl)
|
56
|
+
value = to_extend.fetch(:value)
|
57
|
+
resource = to_extend.fetch(:resource)
|
58
|
+
|
59
|
+
|
60
|
+
extended, time_elapsed = timed do
|
61
|
+
@servers.all? { |s| s.extend_life(resource, value, ttl) }
|
62
|
+
end
|
63
|
+
|
64
|
+
validity = ttl - time_elapsed - drift(ttl)
|
65
|
+
|
66
|
+
if extended
|
67
|
+
{ validity: validity, resource: resource, value: value }
|
68
|
+
else
|
69
|
+
@servers.each { |s| s.unlock(resource, value) }
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def extend_life!(to_extend, ttl)
|
75
|
+
new_lock_info = self.extend_life(to_extend, ttl)
|
76
|
+
raise LockError, 'failed to extend lock' unless new_lock_info
|
77
|
+
end
|
78
|
+
|
55
79
|
# Unlocks a resource.
|
56
80
|
# Params:
|
57
81
|
# +lock_info+:: the lock that has been acquired when you locked the resource.
|
@@ -91,6 +115,16 @@ module Redlock
|
|
91
115
|
end
|
92
116
|
eos
|
93
117
|
|
118
|
+
EXTEND_LOCK_SCRIPT = <<-eos
|
119
|
+
if redis.call("get", KEYS[1]) == ARGV[1] then
|
120
|
+
redis.call("expire", KEYS[1], ARGV[2])
|
121
|
+
return 0
|
122
|
+
else
|
123
|
+
return 1
|
124
|
+
end
|
125
|
+
eos
|
126
|
+
|
127
|
+
|
94
128
|
def initialize(connection)
|
95
129
|
if connection.respond_to?(:client)
|
96
130
|
@redis = connection
|
@@ -107,6 +141,13 @@ module Redlock
|
|
107
141
|
end
|
108
142
|
end
|
109
143
|
|
144
|
+
def extend_life(resource, val, ttl)
|
145
|
+
recover_from_script_flush do
|
146
|
+
rc = @redis.evalsha @extend_lock_script_sha, keys: [resource], argv: [val, ttl]
|
147
|
+
rc == 0
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
110
151
|
def unlock(resource, val)
|
111
152
|
recover_from_script_flush do
|
112
153
|
@redis.evalsha @unlock_script_sha, keys: [resource], argv: [val]
|
@@ -120,6 +161,7 @@ module Redlock
|
|
120
161
|
def load_scripts
|
121
162
|
@unlock_script_sha = @redis.script(:load, UNLOCK_SCRIPT)
|
122
163
|
@lock_script_sha = @redis.script(:load, LOCK_SCRIPT)
|
164
|
+
@extend_lock_script_sha = @redis.script(:load, EXTEND_LOCK_SCRIPT)
|
123
165
|
end
|
124
166
|
|
125
167
|
def recover_from_script_flush
|
data/lib/redlock/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -170,6 +170,40 @@ RSpec.describe Redlock::Client do
|
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
173
|
+
describe "extend" do
|
174
|
+
context 'when lock is available' do
|
175
|
+
before { @lock_info = lock_manager.lock(resource_key, ttl) }
|
176
|
+
after(:each) { lock_manager.unlock(@lock_info) if @lock_info }
|
177
|
+
|
178
|
+
it 'can extend its own lock' do
|
179
|
+
lock_info = lock_manager.extend_life(@lock_info, ttl)
|
180
|
+
expect(lock_info).to be_lock_info_for(resource_key)
|
181
|
+
end
|
182
|
+
|
183
|
+
it "can't extend a nonexistent lock" do
|
184
|
+
lock_manager.unlock(@lock_info)
|
185
|
+
lock_info = lock_manager.extend_life(@lock_info, ttl)
|
186
|
+
expect(lock_info).to eq(false)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "extend!" do
|
192
|
+
context 'when lock is available' do
|
193
|
+
before { @lock_info = lock_manager.lock(resource_key, ttl) }
|
194
|
+
after(:each) { lock_manager.unlock(@lock_info) if @lock_info }
|
195
|
+
|
196
|
+
it 'can extend its own lock' do
|
197
|
+
expect{ lock_manager.extend_life!(@lock_info, ttl) }.to_not raise_error
|
198
|
+
end
|
199
|
+
|
200
|
+
it "can't extend a nonexistent lock" do
|
201
|
+
lock_manager.unlock(@lock_info)
|
202
|
+
expect{ lock_manager.extend_life!(@lock_info, ttl) }.to raise_error(Redlock::LockError)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
173
207
|
describe 'lock!' do
|
174
208
|
context 'when lock is available' do
|
175
209
|
it 'locks' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redlock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leandro Moreira
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|