redlock 0.1.5 → 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 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.