redlock 1.2.0 → 1.2.1

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
  SHA256:
3
- metadata.gz: f27e3a9be9009072c86f2f38a18bdfdcd2f177890aac365d981711dc040acd2e
4
- data.tar.gz: efedd1080833cdee147afe6427878ad0df7c824e981e4e8a48c563ac68350d05
3
+ metadata.gz: a91b03cbb845e7b01556262e80e946e2d72980beeebce12d51380d7c57c57fb9
4
+ data.tar.gz: 73d38bac32a8003a556d3d8967155d15a8edbe988fc43387174ec506b21e8c99
5
5
  SHA512:
6
- metadata.gz: aed115da4ab51ae932533d73e2f2f79d7722e6d77471028bb685d89149d6085fd395af368e9a143231b25b680a57c1ad4d236365396974c12416dac1131cabd8
7
- data.tar.gz: 75b69cd60c2f562b087179dc939c2fb2bbf3514018dd8c302cf4bc2c4cfa4352a1310dd7cfc35042badcd8c86fc5d237d3a6bcafc57385ca2afcc5a2a280c7bf
6
+ metadata.gz: e55aa47e007175e619e22ec2b2ca996add245143290750c79a27fbafc8bb6bd32e5c02b07d9a9752c1ad8cb7f22a10a2b245c9b963c1b4f186427d6c7a987d3a
7
+ data.tar.gz: dd61e0d187a5972ecbe09bde3345c1a6174263f06fca6b7d1da3ce8be19fe5bb69ffca4cfc24073705c5b5a40551bb1a65ffba1358c5fbaf37f10ea46a15a929
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  *.gem
2
2
  coverage/
3
3
  .bundle/
4
+ Gemfile.lock
5
+ dump.rdb
@@ -1,10 +1,23 @@
1
1
  language: ruby
2
- services:
3
- - redis-server
2
+ cache: bundler
3
+ sudo: false
4
+
4
5
  rvm:
5
- - 2.2.2
6
- - 2.5.6
7
- - 2.6.4
6
+ - 2.4.9
7
+ - 2.5.7
8
+ - 2.6.5
9
+ - 2.7.0
10
+ - ruby-head
11
+
12
+ before_install:
13
+ - yes | gem update --system
14
+ - gem install bundler -v "~> 2.0"
15
+
8
16
  script: bundle exec rspec spec
9
- sudo: false
10
- cache: bundler
17
+
18
+ jobs:
19
+ allow_failures:
20
+ - rvm: ruby-head
21
+
22
+ services:
23
+ - redis-server
data/README.md CHANGED
@@ -112,6 +112,68 @@ The above code will also acquire the lock if the previous lock has expired and t
112
112
  lock_manager.lock("resource key", 3000, extend: lock_info, extend_only_if_locked: true)
113
113
  ```
114
114
 
115
+ ### Querying lock status
116
+
117
+ You can check if a resource is locked:
118
+
119
+ ```ruby
120
+ resource = "resource_key"
121
+ lock_info = lock_manager.lock(resource, 2000)
122
+ lock_manager.locked?(resource)
123
+ #=> true
124
+
125
+ lock_manager.unlock(lock_info)
126
+ lock_manager.locked?(resource)
127
+ #=> false
128
+ ```
129
+
130
+ Any caller can call the above method to query the status. If you hold a lock and would like to check if it is valid, you can use the `valid_lock?` method:
131
+
132
+ ```ruby
133
+ lock_info = lock_manager.lock("resource_key", 2000)
134
+ lock_manager.valid_lock?(lock_info)
135
+ #=> true
136
+
137
+ lock_manager.unlock(lock_info)
138
+ lock_manager.valid_lock?(lock_info)
139
+ #=> false
140
+ ```
141
+
142
+ The above methods **are not safe if you are using this to time critical code**, since they return true if the lock has not expired, even if there's only (for example) 1ms left on the lock. If you want to safely time the lock validity, you can use the `get_remaining_ttl_for_lock` and `get_remaining_ttl_for_resource` methods.
143
+
144
+ Use `get_remaining_ttl_for_lock` if you hold a lock and want to check the TTL specifically for your lock:
145
+ ```ruby
146
+ resource = "resource_key"
147
+ lock_info = lock_manager.lock(resource, 2000)
148
+ sleep 1
149
+
150
+ lock_manager.get_remaining_ttl_for_lock(lock_info)
151
+ #=> 986
152
+
153
+ lock_manager.unlock(lock_info)
154
+ lock_manager.get_remaining_ttl_for_lock(lock_info)
155
+ #=> nil
156
+ ```
157
+
158
+ Use `get_remaining_ttl_for_resource` if you do not hold a lock, but want to know the remaining TTL on a locked resource:
159
+ ```ruby
160
+ # Some part of the code
161
+ resource = "resource_key"
162
+ lock_info = lock_manager.lock(resource, 2000)
163
+
164
+ # Some other part of the code
165
+ lock_manager.locked?(resource)
166
+ #=> true
167
+ lock_manager.get_remaining_ttl_for_resource(resource)
168
+ #=> 1975
169
+
170
+ # Sometime later
171
+ lock_manager.locked?(resource)
172
+ #=> false
173
+ lock_manager.get_remaining_ttl_for_resource(resource)
174
+ #=> nil
175
+ ```
176
+
115
177
  ## Redis client configuration
116
178
 
117
179
  `Redlock::Client` expects URLs or Redis objects on initialization. Redis objects should be used for configuring the connection in more detail, i.e. setting username and password.
@@ -11,17 +11,23 @@ services:
11
11
  - REDIS1_PORT=6379
12
12
  - REDIS2_HOST=redis2.local.com
13
13
  - REDIS2_PORT=6379
14
+ - REDIS3_HOST=redis3.local.com
15
+ - REDIS3_PORT=6379
14
16
  - DEFAULT_REDIS_HOST=redis1.local.com
15
17
  - DEFAULT_REDIS_PORT=6379
16
18
  links:
17
19
  - redis1:redis1.local.com
18
20
  - redis2:redis2.local.com
21
+ - redis3:redis3.local.com
19
22
  depends_on:
20
23
  - redis1
21
24
  - redis2
25
+ - redis3
22
26
 
23
27
  redis1:
24
28
  image: redis
25
29
  redis2:
26
30
  image: redis
31
+ redis3:
32
+ image: redis
27
33
 
@@ -102,6 +102,43 @@ module Redlock
102
102
  end
103
103
  end
104
104
 
105
+ # Gets remaining ttl of a resource. The ttl is returned if the holder
106
+ # currently holds the lock and it has not expired, otherwise the method
107
+ # returns nil.
108
+ # Params:
109
+ # +lock_info+:: the lock that has been acquired when you locked the resource
110
+ def get_remaining_ttl_for_lock(lock_info)
111
+ ttl_info = try_get_remaining_ttl(lock_info[:resource])
112
+ return nil if ttl_info.nil? || ttl_info[:value] != lock_info[:value]
113
+ ttl_info[:ttl]
114
+ end
115
+
116
+ # Gets remaining ttl of a resource. If there is no valid lock, the method
117
+ # returns nil.
118
+ # Params:
119
+ # +resource+:: the name of the resource (string) for which to check the ttl
120
+ def get_remaining_ttl_for_resource(resource)
121
+ ttl_info = try_get_remaining_ttl(resource)
122
+ return nil if ttl_info.nil?
123
+ ttl_info[:ttl]
124
+ end
125
+
126
+ # Checks if a resource is locked
127
+ # Params:
128
+ # +lock_info+:: the lock that has been acquired when you locked the resource
129
+ def locked?(resource)
130
+ ttl = get_remaining_ttl_for_resource(resource)
131
+ !(ttl.nil? || ttl.zero?)
132
+ end
133
+
134
+ # Checks if a lock is still valid
135
+ # Params:
136
+ # +lock_info+:: the lock that has been acquired when you locked the resource
137
+ def valid_lock?(lock_info)
138
+ ttl = get_remaining_ttl_for_lock(lock_info)
139
+ !(ttl.nil? || ttl.zero?)
140
+ end
141
+
105
142
  private
106
143
 
107
144
  class RedisInstance
@@ -122,6 +159,10 @@ module Redlock
122
159
  end
123
160
  eos
124
161
 
162
+ PTTL_SCRIPT = <<-eos
163
+ return { redis.call("get", KEYS[1]), redis.call("pttl", KEYS[1]) }
164
+ eos
165
+
125
166
  module ConnectionPoolLike
126
167
  def with
127
168
  yield self
@@ -159,11 +200,20 @@ module Redlock
159
200
  # Nothing to do, unlocking is just a best-effort attempt.
160
201
  end
161
202
 
203
+ def get_remaining_ttl(resource)
204
+ recover_from_script_flush do
205
+ @redis.with { |conn| conn.evalsha @pttl_script_sha, keys: [resource] }
206
+ end
207
+ rescue Redis::BaseConnectionError
208
+ nil
209
+ end
210
+
162
211
  private
163
212
 
164
213
  def load_scripts
165
214
  @unlock_script_sha = @redis.with { |conn| conn.script(:load, UNLOCK_SCRIPT) }
166
215
  @lock_script_sha = @redis.with { |conn| conn.script(:load, LOCK_SCRIPT) }
216
+ @pttl_script_sha = @redis.with { |conn| conn.script(:load, PTTL_SCRIPT) }
167
217
  end
168
218
 
169
219
  def recover_from_script_flush
@@ -228,6 +278,37 @@ module Redlock
228
278
  end
229
279
  end
230
280
 
281
+ def try_get_remaining_ttl(resource)
282
+ # Responses from the servers are a 2 tuple of format [lock_value, ttl].
283
+ # The lock_value is nil if it does not exist. Since servers may have
284
+ # different lock values, the responses are grouped by the lock_value and
285
+ # transofrmed into a hash: { lock_value1 => [ttl1, ttl2, ttl3],
286
+ # lock_value2 => [ttl4, tt5] }
287
+ ttls_by_value, time_elapsed = timed do
288
+ @servers.map { |s| s.get_remaining_ttl(resource) }
289
+ .select { |ttl_tuple| ttl_tuple&.first }
290
+ .group_by(&:first)
291
+ .transform_values { |ttl_tuples| ttl_tuples.map { |t| t.last } }
292
+ end
293
+
294
+ # Authoritative lock value is that which is returned by the majority of
295
+ # servers
296
+ authoritative_value, ttls =
297
+ ttls_by_value.max_by { |(lock_value, ttls)| ttls.length }
298
+
299
+ if ttls && ttls.size >= @quorum
300
+ # Return the minimum TTL of an N/2+1 selection. It will always be
301
+ # correct (it will guarantee that at least N/2+1 servers have a TTL that
302
+ # value or longer)
303
+ min_ttl = ttls.sort.last(@quorum).first
304
+ min_ttl = min_ttl - time_elapsed - drift(min_ttl)
305
+ { value: authoritative_value, ttl: min_ttl }
306
+ else
307
+ # No lock_value is authoritatively held for the resource
308
+ nil
309
+ end
310
+ end
311
+
231
312
  def drift(ttl)
232
313
  # Add 2 milliseconds to the drift to account for Redis expires
233
314
  # precision, which is 1 millisecond, plus 1 millisecond min drift
@@ -1,3 +1,5 @@
1
+ require 'redlock'
2
+
1
3
  module Redlock
2
4
  class Client
3
5
  class << self
@@ -1,3 +1,3 @@
1
1
  module Redlock
2
- VERSION = '1.2.0'
2
+ VERSION = '1.2.1'
3
3
  end
@@ -1,27 +1,29 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'redlock/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "redlock"
8
+ spec.name = 'redlock'
8
9
  spec.version = Redlock::VERSION
9
- spec.authors = ["Leandro Moreira"]
10
- spec.email = ["leandro.ribeiro.moreira@gmail.com"]
11
- spec.summary = %q{Distributed lock using Redis written in Ruby.}
12
- spec.description = %q{Distributed lock using Redis written in Ruby. Highly inspired by https://github.com/antirez/redlock-rb.}
13
- spec.homepage = "https://github.com/leandromoreira/redlock-rb"
10
+ spec.authors = ['Leandro Moreira']
11
+ spec.email = ['leandro.ribeiro.moreira@gmail.com']
12
+ spec.summary = 'Distributed lock using Redis written in Ruby.'
13
+ spec.description = 'Distributed lock using Redis written in Ruby. Highly inspired by https://github.com/antirez/redlock-rb.'
14
+ spec.homepage = 'https://github.com/leandromoreira/redlock-rb'
14
15
  spec.license = 'BSD-2-Clause'
15
16
 
16
17
  spec.files = `git ls-files -z`.split("\x0")
17
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
+ spec.require_paths = ['lib']
20
21
 
21
22
  spec.add_dependency 'redis', '>= 3.0.0', '< 5.0'
22
23
 
23
- spec.add_development_dependency "coveralls", "~> 0.8"
24
+ spec.add_development_dependency 'connection_pool', '~> 2.2'
25
+ spec.add_development_dependency 'coveralls', '~> 0.8'
26
+ spec.add_development_dependency 'json', '>= 2.3.0', '~> 2.3.1'
24
27
  spec.add_development_dependency 'rake', '>= 11.1.2', '~> 13.0'
25
28
  spec.add_development_dependency 'rspec', '~> 3', '>= 3.0.0'
26
- spec.add_development_dependency 'connection_pool', '~> 2.2'
27
29
  end
@@ -7,13 +7,22 @@ RSpec.describe Redlock::Client do
7
7
  # It is recommended to have at least 3 servers in production
8
8
  let(:lock_manager_opts) { { retry_count: 3 } }
9
9
  let(:lock_manager) { Redlock::Client.new(Redlock::Client::DEFAULT_REDIS_URLS, lock_manager_opts) }
10
- let(:redis_client) { Redis.new }
10
+ let(:redis_client) { Redis.new(url: "redis://#{redis1_host}:#{redis1_port}") }
11
11
  let(:resource_key) { SecureRandom.hex(3) }
12
12
  let(:ttl) { 1000 }
13
13
  let(:redis1_host) { ENV["REDIS1_HOST"] || "localhost" }
14
14
  let(:redis1_port) { ENV["REDIS1_PORT"] || "6379" }
15
15
  let(:redis2_host) { ENV["REDIS2_HOST"] || "127.0.0.1" }
16
16
  let(:redis2_port) { ENV["REDIS2_PORT"] || "6379" }
17
+ let(:redis3_host) { ENV["REDIS3_HOST"] || "127.0.0.1" }
18
+ let(:redis3_port) { ENV["REDIS3_PORT"] || "6379" }
19
+ let(:unreachable_redis) {
20
+ redis = Redis.new(url: 'redis://localhost:46864')
21
+ def redis.with
22
+ yield self
23
+ end
24
+ redis
25
+ }
17
26
 
18
27
  describe 'initialize' do
19
28
  it 'accepts both redis URLs and Redis objects' do
@@ -212,14 +221,6 @@ RSpec.describe Redlock::Client do
212
221
  end
213
222
  end
214
223
 
215
- def unreachable_redis
216
- redis = Redis.new(url: 'redis://localhost:46864')
217
- def redis.with
218
- yield self
219
- end
220
- redis
221
- end
222
-
223
224
  context 'when script cache has been flushed' do
224
225
  before(:each) do
225
226
  @manipulated_instance = lock_manager.instance_variable_get(:@servers).first
@@ -367,6 +368,154 @@ RSpec.describe Redlock::Client do
367
368
  end
368
369
  end
369
370
 
371
+ describe 'get_remaining_ttl_for_resource' do
372
+ context 'when lock is valid' do
373
+ after(:each) { lock_manager.unlock(@lock_info) if @lock_info }
374
+
375
+ it 'gets the remaining ttl of a lock' do
376
+ ttl = 20_000
377
+ @lock_info = lock_manager.lock(resource_key, ttl)
378
+ remaining_ttl = lock_manager.get_remaining_ttl_for_resource(resource_key)
379
+ expect(remaining_ttl).to be_within(300).of(ttl)
380
+ end
381
+
382
+ context 'when servers respond with varying ttls' do
383
+ let (:servers) {
384
+ [
385
+ "redis://#{redis1_host}:#{redis1_port}",
386
+ "redis://#{redis2_host}:#{redis2_port}",
387
+ "redis://#{redis3_host}:#{redis3_port}"
388
+ ]
389
+ }
390
+ let (:redlock) { Redlock::Client.new(servers) }
391
+ after(:each) { redlock.unlock(@lock_info) if @lock_info }
392
+
393
+ it 'returns the minimum ttl value' do
394
+ ttl = 20_000
395
+ @lock_info = redlock.lock(resource_key, ttl)
396
+
397
+ # Mock redis server responses to return different ttls
398
+ returned_ttls = [20_000, 15_000, 10_000]
399
+ redlock.instance_variable_get(:@servers).each_with_index do |server, index|
400
+ allow(server).to(receive(:get_remaining_ttl))
401
+ .with(resource_key)
402
+ .and_return([@lock_info[:value], returned_ttls[index]])
403
+ end
404
+
405
+ remaining_ttl = redlock.get_remaining_ttl_for_lock(@lock_info)
406
+
407
+ # Assert that the TTL is closest to the closest to the correct value
408
+ expect(remaining_ttl).to be_within(300).of(returned_ttls[1])
409
+ end
410
+ end
411
+ end
412
+
413
+ context 'when lock is not valid' do
414
+ it 'returns nil' do
415
+ lock_info = lock_manager.lock(resource_key, ttl)
416
+ lock_manager.unlock(lock_info)
417
+ remaining_ttl = lock_manager.get_remaining_ttl_for_resource(resource_key)
418
+ expect(remaining_ttl).to be_nil
419
+ end
420
+ end
421
+
422
+ context 'when server goes away' do
423
+ after(:each) { lock_manager.unlock(@lock_info) if @lock_info }
424
+
425
+ it 'does not raise an error on connection issues' do
426
+ @lock_info = lock_manager.lock(resource_key, ttl)
427
+
428
+ # Replace redis with unreachable instance
429
+ redis_instance = lock_manager.instance_variable_get(:@servers).first
430
+ old_redis = redis_instance.instance_variable_get(:@redis)
431
+ redis_instance.instance_variable_set(:@redis, unreachable_redis)
432
+
433
+ expect {
434
+ remaining_ttl = lock_manager.get_remaining_ttl_for_resource(resource_key)
435
+ expect(remaining_ttl).to be_nil
436
+ }.to_not raise_error
437
+ end
438
+ end
439
+
440
+ context 'when a server comes back' do
441
+ after(:each) { lock_manager.unlock(@lock_info) if @lock_info }
442
+
443
+ it 'recovers from connection issues' do
444
+ @lock_info = lock_manager.lock(resource_key, ttl)
445
+
446
+ # Replace redis with unreachable instance
447
+ redis_instance = lock_manager.instance_variable_get(:@servers).first
448
+ old_redis = redis_instance.instance_variable_get(:@redis)
449
+ redis_instance.instance_variable_set(:@redis, unreachable_redis)
450
+
451
+ expect(lock_manager.get_remaining_ttl_for_resource(resource_key)).to be_nil
452
+
453
+ # Restore redis
454
+ redis_instance.instance_variable_set(:@redis, old_redis)
455
+ expect(lock_manager.get_remaining_ttl_for_resource(resource_key)).to be_truthy
456
+ end
457
+ end
458
+ end
459
+
460
+ describe 'get_remaining_ttl_for_lock' do
461
+ context 'when lock is valid' do
462
+ it 'gets the remaining ttl of a lock' do
463
+ ttl = 20_000
464
+ lock_info = lock_manager.lock(resource_key, ttl)
465
+ remaining_ttl = lock_manager.get_remaining_ttl_for_lock(lock_info)
466
+ expect(remaining_ttl).to be_within(300).of(ttl)
467
+ lock_manager.unlock(lock_info)
468
+ end
469
+ end
470
+
471
+ context 'when lock is not valid' do
472
+ it 'returns nil' do
473
+ lock_info = lock_manager.lock(resource_key, ttl)
474
+ lock_manager.unlock(lock_info)
475
+ remaining_ttl = lock_manager.get_remaining_ttl_for_lock(lock_info)
476
+ expect(remaining_ttl).to be_nil
477
+ end
478
+ end
479
+ end
480
+
481
+ describe 'locked?' do
482
+ context 'when lock is available' do
483
+ after(:each) { lock_manager.unlock(@lock_info) if @lock_info }
484
+
485
+ it 'returns true' do
486
+ @lock_info = lock_manager.lock(resource_key, ttl)
487
+ expect(lock_manager).to be_locked(resource_key)
488
+ end
489
+ end
490
+
491
+ context 'when lock is not available' do
492
+ it 'returns false' do
493
+ lock_info = lock_manager.lock(resource_key, ttl)
494
+ lock_manager.unlock(lock_info)
495
+ expect(lock_manager).not_to be_locked(resource_key)
496
+ end
497
+ end
498
+ end
499
+
500
+ describe 'valid_lock?' do
501
+ context 'when lock is available' do
502
+ after(:each) { lock_manager.unlock(@lock_info) if @lock_info }
503
+
504
+ it 'returns true' do
505
+ @lock_info = lock_manager.lock(resource_key, ttl)
506
+ expect(lock_manager).to be_valid_lock(@lock_info)
507
+ end
508
+ end
509
+
510
+ context 'when lock is not available' do
511
+ it 'returns false' do
512
+ lock_info = lock_manager.lock(resource_key, ttl)
513
+ lock_manager.unlock(lock_info)
514
+ expect(lock_manager).not_to be_valid_lock(lock_info)
515
+ end
516
+ end
517
+ end
518
+
370
519
  describe '#default_time_source' do
371
520
  context 'when CLOCK_MONOTONIC is available (MRI, JRuby)' do
372
521
  it 'returns a callable using Process.clock_gettime()' 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: 1.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leandro Moreira
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-29 00:00:00.000000000 Z
11
+ date: 2020-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -30,6 +30,20 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '5.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: connection_pool
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.2'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.2'
33
47
  - !ruby/object:Gem::Dependency
34
48
  name: coveralls
35
49
  requirement: !ruby/object:Gem::Requirement
@@ -44,6 +58,26 @@ dependencies:
44
58
  - - "~>"
45
59
  - !ruby/object:Gem::Version
46
60
  version: '0.8'
61
+ - !ruby/object:Gem::Dependency
62
+ name: json
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 2.3.0
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: 2.3.1
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.3.0
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: 2.3.1
47
81
  - !ruby/object:Gem::Dependency
48
82
  name: rake
49
83
  requirement: !ruby/object:Gem::Requirement
@@ -84,20 +118,6 @@ dependencies:
84
118
  - - ">="
85
119
  - !ruby/object:Gem::Version
86
120
  version: 3.0.0
87
- - !ruby/object:Gem::Dependency
88
- name: connection_pool
89
- requirement: !ruby/object:Gem::Requirement
90
- requirements:
91
- - - "~>"
92
- - !ruby/object:Gem::Version
93
- version: '2.2'
94
- type: :development
95
- prerelease: false
96
- version_requirements: !ruby/object:Gem::Requirement
97
- requirements:
98
- - - "~>"
99
- - !ruby/object:Gem::Version
100
- version: '2.2'
101
121
  description: Distributed lock using Redis written in Ruby. Highly inspired by https://github.com/antirez/redlock-rb.
102
122
  email:
103
123
  - leandro.ribeiro.moreira@gmail.com
@@ -110,7 +130,6 @@ files:
110
130
  - ".travis.yml"
111
131
  - CONTRIBUTORS
112
132
  - Gemfile
113
- - Gemfile.lock
114
133
  - LICENSE
115
134
  - Makefile
116
135
  - README.md
@@ -144,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
163
  - !ruby/object:Gem::Version
145
164
  version: '0'
146
165
  requirements: []
147
- rubygems_version: 3.1.2
166
+ rubygems_version: 3.1.4
148
167
  signing_key:
149
168
  specification_version: 4
150
169
  summary: Distributed lock using Redis written in Ruby.
@@ -1,56 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- redlock (1.2.0)
5
- redis (>= 3.0.0, < 5.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- connection_pool (2.2.2)
11
- coveralls (0.8.22)
12
- json (>= 1.8, < 3)
13
- simplecov (~> 0.16.1)
14
- term-ansicolor (~> 1.3)
15
- thor (~> 0.19.4)
16
- tins (~> 1.6)
17
- diff-lcs (1.3)
18
- docile (1.3.1)
19
- json (2.1.0)
20
- rake (13.0.1)
21
- redis (4.1.1)
22
- rspec (3.5.0)
23
- rspec-core (~> 3.5.0)
24
- rspec-expectations (~> 3.5.0)
25
- rspec-mocks (~> 3.5.0)
26
- rspec-core (3.5.4)
27
- rspec-support (~> 3.5.0)
28
- rspec-expectations (3.5.0)
29
- diff-lcs (>= 1.2.0, < 2.0)
30
- rspec-support (~> 3.5.0)
31
- rspec-mocks (3.5.0)
32
- diff-lcs (>= 1.2.0, < 2.0)
33
- rspec-support (~> 3.5.0)
34
- rspec-support (3.5.0)
35
- simplecov (0.16.1)
36
- docile (~> 1.1)
37
- json (>= 1.8, < 3)
38
- simplecov-html (~> 0.10.0)
39
- simplecov-html (0.10.2)
40
- term-ansicolor (1.6.0)
41
- tins (~> 1.0)
42
- thor (0.19.4)
43
- tins (1.16.3)
44
-
45
- PLATFORMS
46
- ruby
47
-
48
- DEPENDENCIES
49
- connection_pool (~> 2.2)
50
- coveralls (~> 0.8)
51
- rake (~> 13.0, >= 11.1.2)
52
- redlock!
53
- rspec (~> 3, >= 3.0.0)
54
-
55
- BUNDLED WITH
56
- 1.17.2