redlock 0.1.5 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZWE3MWMxNjdhNDQ5OTE3ZDk4ODM5YTk0YzJhMTdiYmIyZjMzNWNlYg==
5
- data.tar.gz: !binary |-
6
- ZmQ4YmY4ODEzZDZlOWVmNmZlYzBmMTFiZDIzNjg2NDk1NWYyYmEzZg==
2
+ SHA1:
3
+ metadata.gz: 86073e680a1deb905852ddfcd28042cf81729875
4
+ data.tar.gz: 76cffc3d01b4fa649ad4ae4276149453282c0ed4
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZTdjMTdkNjZmNDBkNmQyYmIyMmQ4OTJjOTBlNGQxZmNlNGIxY2NlZjY0NTIx
10
- NDI1YTRmYTkyYjc4ZDY1OTc3ZmFjODI5Y2UwYzVjYzI1MTcyYmQ0Y2M2MGY3
11
- MTAxMDRlMWFmMjcyMjI2ZDExMDU3MTI0ODU0N2UyNjQyMjIwNGM=
12
- data.tar.gz: !binary |-
13
- ZWI3MzI4NjQzZjEyZGIyMTU0OTA3YTIxMzIxMTFiZjExYzAzNTMwMTgzZDdm
14
- OWY5MzFiMWIwOWRhNmUwNzVjY2M5MzI5M2JiMmUyMzUwNjM0MzI0YWYxZWQy
15
- Y2ZkZTJkMzdhOWU1OTE0MTFlNTcxZjNmNWMzN2QyZDgzZmZlNmQ=
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,57 +1,55 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- redlock (0.1.5)
5
- redis (~> 3, >= 3.0.5)
4
+ redlock (0.1.7)
5
+ redis (~> 3, >= 3.3.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- coveralls (0.7.11)
11
- multi_json (~> 1.10)
12
- rest-client (>= 1.6.8, < 2)
13
- simplecov (~> 0.9.1)
10
+ coveralls (0.8.13)
11
+ json (~> 1.8)
12
+ simplecov (~> 0.11.0)
14
13
  term-ansicolor (~> 1.3)
15
14
  thor (~> 0.19.1)
15
+ tins (~> 1.6.0)
16
16
  diff-lcs (1.2.5)
17
17
  docile (1.1.5)
18
- mime-types (2.4.3)
19
- multi_json (1.11.0)
20
- netrc (0.10.3)
21
- rake (10.4.2)
22
- redis (3.2.2)
23
- rest-client (1.7.3)
24
- mime-types (>= 1.16, < 3.0)
25
- netrc (~> 0.7)
26
- rspec (3.2.0)
27
- rspec-core (~> 3.2.0)
28
- rspec-expectations (~> 3.2.0)
29
- rspec-mocks (~> 3.2.0)
30
- rspec-core (3.2.2)
31
- rspec-support (~> 3.2.0)
32
- rspec-expectations (3.2.0)
18
+ json (1.8.3)
19
+ rake (11.1.2)
20
+ redis (3.3.0)
21
+ rspec (3.4.0)
22
+ rspec-core (~> 3.4.0)
23
+ rspec-expectations (~> 3.4.0)
24
+ rspec-mocks (~> 3.4.0)
25
+ rspec-core (3.4.4)
26
+ rspec-support (~> 3.4.0)
27
+ rspec-expectations (3.4.0)
33
28
  diff-lcs (>= 1.2.0, < 2.0)
34
- rspec-support (~> 3.2.0)
35
- rspec-mocks (3.2.1)
29
+ rspec-support (~> 3.4.0)
30
+ rspec-mocks (3.4.1)
36
31
  diff-lcs (>= 1.2.0, < 2.0)
37
- rspec-support (~> 3.2.0)
38
- rspec-support (3.2.2)
39
- simplecov (0.9.2)
32
+ rspec-support (~> 3.4.0)
33
+ rspec-support (3.4.1)
34
+ simplecov (0.11.2)
40
35
  docile (~> 1.1.0)
41
- multi_json (~> 1.0)
42
- simplecov-html (~> 0.9.0)
43
- simplecov-html (0.9.0)
44
- term-ansicolor (1.3.0)
36
+ json (~> 1.8)
37
+ simplecov-html (~> 0.10.0)
38
+ simplecov-html (0.10.0)
39
+ term-ansicolor (1.3.2)
45
40
  tins (~> 1.0)
46
41
  thor (0.19.1)
47
- tins (1.3.5)
42
+ tins (1.6.0)
48
43
 
49
44
  PLATFORMS
50
45
  ruby
51
46
 
52
47
  DEPENDENCIES
53
- bundler (~> 1.7)
54
- coveralls
55
- rake (~> 10.0)
48
+ bundler (~> 1.12, >= 1.12.3)
49
+ coveralls (~> 0.8.13)
50
+ rake (~> 11.1, >= 11.1.2)
56
51
  redlock!
57
- rspec (~> 3.1)
52
+ rspec (~> 3.4, >= 3.4.0)
53
+
54
+ BUNDLED WITH
55
+ 1.12.3
data/README.md CHANGED
@@ -19,6 +19,10 @@
19
19
 
20
20
  This is an implementation of a proposed [distributed lock algorithm with Redis](http://redis.io/topics/distlock). It started as a fork from [antirez implementation.](https://github.com/antirez/redlock-rb)
21
21
 
22
+ ## Compatibility
23
+
24
+ Redlock works with Redis versions 2.6 or later.
25
+
22
26
  ## Installation
23
27
 
24
28
  Add this line to your application's Gemfile:
@@ -91,6 +95,22 @@ rescue Redlock::LockError
91
95
  end
92
96
  ```
93
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
+
94
114
  ## Run tests
95
115
 
96
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.5'
2
+ VERSION = '0.1.7'
3
3
  end
data/redlock.gemspec CHANGED
@@ -18,10 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency 'redis', '~> 3', '>= 3.0.5'
21
+ spec.add_dependency 'redis', '~> 3', '>= 3.3.0'
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.7"
24
- spec.add_development_dependency "coveralls"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "rspec", "~> 3.1"
23
+ spec.add_development_dependency 'bundler', '~> 1.12', '>= 1.12.3'
24
+ spec.add_development_dependency "coveralls", "~> 0.8.13"
25
+ spec.add_development_dependency 'rake', '~> 11.1', '>= 11.1.2'
26
+ spec.add_development_dependency 'rspec', '~> 3.4', '>= 3.4.0'
27
27
  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,91 +1,109 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redlock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
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: 2015-12-01 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
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3'
20
- - - ! '>='
20
+ - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 3.0.5
22
+ version: 3.3.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - ~>
27
+ - - "~>"
28
28
  - !ruby/object:Gem::Version
29
29
  version: '3'
30
- - - ! '>='
30
+ - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 3.0.5
32
+ version: 3.3.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: bundler
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - ~>
37
+ - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1.7'
39
+ version: '1.12'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.12.3
40
43
  type: :development
41
44
  prerelease: false
42
45
  version_requirements: !ruby/object:Gem::Requirement
43
46
  requirements:
44
- - - ~>
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.12'
50
+ - - ">="
45
51
  - !ruby/object:Gem::Version
46
- version: '1.7'
52
+ version: 1.12.3
47
53
  - !ruby/object:Gem::Dependency
48
54
  name: coveralls
49
55
  requirement: !ruby/object:Gem::Requirement
50
56
  requirements:
51
- - - ! '>='
57
+ - - "~>"
52
58
  - !ruby/object:Gem::Version
53
- version: '0'
59
+ version: 0.8.13
54
60
  type: :development
55
61
  prerelease: false
56
62
  version_requirements: !ruby/object:Gem::Requirement
57
63
  requirements:
58
- - - ! '>='
64
+ - - "~>"
59
65
  - !ruby/object:Gem::Version
60
- version: '0'
66
+ version: 0.8.13
61
67
  - !ruby/object:Gem::Dependency
62
68
  name: rake
63
69
  requirement: !ruby/object:Gem::Requirement
64
70
  requirements:
65
- - - ~>
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '11.1'
74
+ - - ">="
66
75
  - !ruby/object:Gem::Version
67
- version: '10.0'
76
+ version: 11.1.2
68
77
  type: :development
69
78
  prerelease: false
70
79
  version_requirements: !ruby/object:Gem::Requirement
71
80
  requirements:
72
- - - ~>
81
+ - - "~>"
73
82
  - !ruby/object:Gem::Version
74
- version: '10.0'
83
+ version: '11.1'
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: 11.1.2
75
87
  - !ruby/object:Gem::Dependency
76
88
  name: rspec
77
89
  requirement: !ruby/object:Gem::Requirement
78
90
  requirements:
79
- - - ~>
91
+ - - "~>"
92
+ - !ruby/object:Gem::Version
93
+ version: '3.4'
94
+ - - ">="
80
95
  - !ruby/object:Gem::Version
81
- version: '3.1'
96
+ version: 3.4.0
82
97
  type: :development
83
98
  prerelease: false
84
99
  version_requirements: !ruby/object:Gem::Requirement
85
100
  requirements:
86
- - - ~>
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.4'
104
+ - - ">="
87
105
  - !ruby/object:Gem::Version
88
- version: '3.1'
106
+ version: 3.4.0
89
107
  description: Distributed lock using Redis written in Ruby. Highly inspired by https://github.com/antirez/redlock-rb.
90
108
  email:
91
109
  - leandro.ribeiro.moreira@gmail.com
@@ -93,9 +111,9 @@ executables: []
93
111
  extensions: []
94
112
  extra_rdoc_files: []
95
113
  files:
96
- - .gitignore
97
- - .rspec
98
- - .travis.yml
114
+ - ".gitignore"
115
+ - ".rspec"
116
+ - ".travis.yml"
99
117
  - CONTRIBUTORS
100
118
  - Gemfile
101
119
  - Gemfile.lock
@@ -120,17 +138,17 @@ require_paths:
120
138
  - lib
121
139
  required_ruby_version: !ruby/object:Gem::Requirement
122
140
  requirements:
123
- - - ! '>='
141
+ - - ">="
124
142
  - !ruby/object:Gem::Version
125
143
  version: '0'
126
144
  required_rubygems_version: !ruby/object:Gem::Requirement
127
145
  requirements:
128
- - - ! '>='
146
+ - - ">="
129
147
  - !ruby/object:Gem::Version
130
148
  version: '0'
131
149
  requirements: []
132
150
  rubyforge_project:
133
- rubygems_version: 2.4.6
151
+ rubygems_version: 2.6.3
134
152
  signing_key:
135
153
  specification_version: 4
136
154
  summary: Distributed lock using Redis written in Ruby.