redlock 0.1.1 → 0.1.2
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 +5 -13
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/redlock/client.rb +9 -1
- data/lib/redlock/testing.rb +37 -0
- data/lib/redlock/version.rb +1 -1
- data/spec/client_spec.rb +2 -2
- data/spec/spec_helper.rb +0 -1
- data/spec/testing_spec.rb +45 -0
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NjMwOGMxNTRkMDliODFmYjI3YWY5MWQ3ZTdjMjUzMDNlNTdiNDQ4Yg==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e2d0a189eba4a2f362d02f034cfa0957eba666eb
|
4
|
+
data.tar.gz: 18f9e90023c218eb9b5d65a71946b39fb98a8617
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
NDI2ODJmYzU5MGI2YjM3MmMxNGQwNTRlYzM4ZTE0MWNhNmQyYWVlNGUyYmU4
|
11
|
-
YWM0OTUyMzQwNzdlNTk2ZTNiNGE4OTdjYTQzYmYwMjBjYjU5YmE=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
N2Q1ZTcwZWRlNDYyZjY0MzY4MDA4ZTVhMjEwNTE3N2Q4MWZmOTY0MDA0MmIx
|
14
|
-
MjVlYzM3ZWQ1Y2RkODJiOTI0ZTZiYWQ3MjdmZWU2NWZkNzMyMGM2YzM2OTUy
|
15
|
-
NWJmMjNmNjU0YzgyNDNkNGVhMDM2OWJjZmMzY2NhMWY4MzVjZjI=
|
6
|
+
metadata.gz: 65cd0b7c60b9756eba2f0fcce27677b9f26e32db74f3cbea7f036744ae52bfd0e50f8ce72cddb538fafc49a409c0f7a6257976d9234be8305d8a77151958980d
|
7
|
+
data.tar.gz: 0531fe15435ad4601ad83c8aa107ac6e3073f4f2be49682c74ff379f9b9c20f603e140b51c604b5baffdfb7650a3e4762cdea9495870fa1b684f99bcbab6930d
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -84,7 +84,7 @@ end
|
|
84
84
|
Make sure you have at least 1 redis instances up.
|
85
85
|
|
86
86
|
$ rspec
|
87
|
-
|
87
|
+
|
88
88
|
## Disclaimer
|
89
89
|
|
90
90
|
This code implements an algorithm which is currently a proposal, it was not formally analyzed. Make sure to understand how it works before using it in your production environments. You can see discussion about this approach at [reddit](http://www.reddit.com/r/programming/comments/2nt0nq/distributed_lock_using_redis_implemented_in_ruby/).
|
data/lib/redlock/client.rb
CHANGED
@@ -74,6 +74,8 @@ module Redlock
|
|
74
74
|
else
|
75
75
|
@redis = Redis.new(connection)
|
76
76
|
end
|
77
|
+
|
78
|
+
load_scripts
|
77
79
|
end
|
78
80
|
|
79
81
|
def lock(resource, val, ttl)
|
@@ -81,10 +83,16 @@ module Redlock
|
|
81
83
|
end
|
82
84
|
|
83
85
|
def unlock(resource, val)
|
84
|
-
@redis.
|
86
|
+
@redis.evalsha(@unlock_script_sha, keys: [resource], argv: [val])
|
85
87
|
rescue
|
86
88
|
# Nothing to do, unlocking is just a best-effort attempt.
|
87
89
|
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def load_scripts
|
94
|
+
@unlock_script_sha = @redis.script(:load, UNLOCK_SCRIPT)
|
95
|
+
end
|
88
96
|
end
|
89
97
|
|
90
98
|
def try_lock_instances(resource, ttl)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Redlock
|
2
|
+
class Client
|
3
|
+
attr_writer :testing_mode
|
4
|
+
|
5
|
+
alias_method :try_lock_instances_without_testing, :try_lock_instances
|
6
|
+
|
7
|
+
def try_lock_instances(resource, ttl)
|
8
|
+
if @testing_mode == :bypass
|
9
|
+
{
|
10
|
+
validity: ttl,
|
11
|
+
resource: resource,
|
12
|
+
value: SecureRandom.uuid
|
13
|
+
}
|
14
|
+
elsif @testing_mode == :fail
|
15
|
+
false
|
16
|
+
else
|
17
|
+
try_lock_instances_without_testing resource, ttl
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_method :unlock_without_testing, :unlock
|
22
|
+
|
23
|
+
def unlock(lock_info)
|
24
|
+
unlock_without_testing lock_info unless @testing_mode == :bypass
|
25
|
+
end
|
26
|
+
|
27
|
+
class RedisInstance
|
28
|
+
def load_scripts
|
29
|
+
begin
|
30
|
+
@unlock_script_sha = @redis.script(:load, UNLOCK_SCRIPT)
|
31
|
+
rescue Redis::CommandError
|
32
|
+
# ignore
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/redlock/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -9,14 +9,14 @@ RSpec.describe Redlock::Client do
|
|
9
9
|
|
10
10
|
describe 'initialize' do
|
11
11
|
it 'accepts both redis URLs and Redis objects' do
|
12
|
-
servers = [ 'redis://localhost:6379', Redis.new(url: 'redis://
|
12
|
+
servers = [ 'redis://localhost:6379', Redis.new(url: 'redis://127.0.0.1:6379') ]
|
13
13
|
redlock = Redlock::Client.new(servers)
|
14
14
|
|
15
15
|
redlock_servers = redlock.instance_variable_get(:@servers).map do |s|
|
16
16
|
s.instance_variable_get(:@redis).client.host
|
17
17
|
end
|
18
18
|
|
19
|
-
expect(redlock_servers).to match_array(%w{ localhost
|
19
|
+
expect(redlock_servers).to match_array(%w{ localhost 127.0.0.1 })
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
require 'redlock/testing'
|
5
|
+
|
6
|
+
RSpec.describe Redlock::Client do
|
7
|
+
let(:lock_manager) { Redlock::Client.new }
|
8
|
+
let(:resource_key) { SecureRandom.hex(3) }
|
9
|
+
let(:ttl) { 1000 }
|
10
|
+
|
11
|
+
describe '(testing mode)' do
|
12
|
+
describe 'try_lock_instances' do
|
13
|
+
context 'when testing with bypass mode' do
|
14
|
+
before { lock_manager.testing_mode = :bypass }
|
15
|
+
|
16
|
+
it 'bypasses the redis servers' do
|
17
|
+
expect(lock_manager).to_not receive(:try_lock_instances_without_testing)
|
18
|
+
lock_manager.lock(resource_key, ttl) do |lock_info|
|
19
|
+
expect(lock_info).to be_lock_info_for(resource_key)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when testing with fail mode' do
|
25
|
+
before { lock_manager.testing_mode = :fail }
|
26
|
+
|
27
|
+
it 'fails' do
|
28
|
+
expect(lock_manager).to_not receive(:try_lock_instances_without_testing)
|
29
|
+
lock_manager.lock(resource_key, ttl) do |lock_info|
|
30
|
+
expect(lock_info).to eql(false)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when testing is disabled' do
|
36
|
+
before { lock_manager.testing_mode = nil }
|
37
|
+
|
38
|
+
it 'works as usual' do
|
39
|
+
expect(lock_manager).to receive(:try_lock_instances_without_testing)
|
40
|
+
lock_manager.lock(resource_key, ttl) { |lock_info| }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
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.2
|
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-
|
11
|
+
date: 2015-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -17,7 +17,7 @@ dependencies:
|
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '3'
|
20
|
-
- -
|
20
|
+
- - '>='
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: 3.0.5
|
23
23
|
type: :runtime
|
@@ -27,7 +27,7 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '3'
|
30
|
-
- -
|
30
|
+
- - '>='
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 3.0.5
|
33
33
|
- !ruby/object:Gem::Dependency
|
@@ -48,14 +48,14 @@ dependencies:
|
|
48
48
|
name: coveralls
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
|
-
- -
|
51
|
+
- - '>='
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '0'
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
|
-
- -
|
58
|
+
- - '>='
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
@@ -104,10 +104,12 @@ files:
|
|
104
104
|
- Rakefile
|
105
105
|
- lib/redlock.rb
|
106
106
|
- lib/redlock/client.rb
|
107
|
+
- lib/redlock/testing.rb
|
107
108
|
- lib/redlock/version.rb
|
108
109
|
- redlock.gemspec
|
109
110
|
- spec/client_spec.rb
|
110
111
|
- spec/spec_helper.rb
|
112
|
+
- spec/testing_spec.rb
|
111
113
|
homepage: https://github.com/leandromoreira/redlock-rb
|
112
114
|
licenses:
|
113
115
|
- BSD-2-Clause
|
@@ -118,12 +120,12 @@ require_paths:
|
|
118
120
|
- lib
|
119
121
|
required_ruby_version: !ruby/object:Gem::Requirement
|
120
122
|
requirements:
|
121
|
-
- -
|
123
|
+
- - '>='
|
122
124
|
- !ruby/object:Gem::Version
|
123
125
|
version: '0'
|
124
126
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
127
|
requirements:
|
126
|
-
- -
|
128
|
+
- - '>='
|
127
129
|
- !ruby/object:Gem::Version
|
128
130
|
version: '0'
|
129
131
|
requirements: []
|
@@ -135,3 +137,4 @@ summary: Distributed lock using Redis written in Ruby.
|
|
135
137
|
test_files:
|
136
138
|
- spec/client_spec.rb
|
137
139
|
- spec/spec_helper.rb
|
140
|
+
- spec/testing_spec.rb
|