redlock 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ea5ebfa119462a5500c078e0f113480b0178429
4
- data.tar.gz: aad002651ed21a7782d63794f7d4cb9073e529e9
3
+ metadata.gz: 86073e680a1deb905852ddfcd28042cf81729875
4
+ data.tar.gz: 76cffc3d01b4fa649ad4ae4276149453282c0ed4
5
5
  SHA512:
6
- metadata.gz: b099d48798f351476f7a225a924c6a0c2671b4ef25aad314f573b152a5ca587d43fdb2b29ca4fc6dc1031e9dc6060c99dace1f96eb06b57a47dc544a2df20901
7
- data.tar.gz: ac4a7b903e6913e691f99b536cd31462a2da41fe14cfa23fd30665b35bae78d9a8da1e2495721f9aa53b6bcb44fc922423e86cf56cf14bec5f82ef9e38698351
6
+ metadata.gz: 8b0687bd912eff82bb3f4607de313d681d1e18971cbd3b6b484bae0fabae38b258ef423f0c00256b45e633fbc83abea9b38c57fbf08ce4d6567a2c254701eeb7
7
+ data.tar.gz: 86dc485ebc704b9d46bd6878d18f9b7403c13840721a2475b4b61b5c7b4099a40db3375045df8c8be7e9270d52f9560854b489a3656805046d995e253b1d126b
data/.travis.yml CHANGED
@@ -2,7 +2,7 @@ language: ruby
2
2
  services:
3
3
  - redis-server
4
4
  rvm:
5
- - "2.0.0"
5
+ - "2.2.2"
6
6
  script: bundle exec rspec spec
7
7
  sudo: false
8
8
  cache: bundler
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- redlock (0.1.6)
4
+ redlock (0.1.7)
5
5
  redis (~> 3, >= 3.3.0)
6
6
 
7
7
  GEM
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.
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Redlock
2
- VERSION = '0.1.6'
2
+ VERSION = '0.1.7'
3
3
  end
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.6
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-12 00:00:00.000000000 Z
11
+ date: 2016-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis