redis-mutex 2.1.1 → 3.0.0
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 +4 -4
- data/.travis.yml +5 -8
- data/README.md +8 -2
- data/lib/redis/mutex/macro.rb +10 -2
- data/redis-mutex.gemspec +1 -1
- data/spec/redis_mutex_macro_spec.rb +81 -0
- data/spec/redis_mutex_spec.rb +0 -22
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31cd09963698ff45f5481699862332a7299ea0fb
|
4
|
+
data.tar.gz: ca58764a3e815285dc03a03650969f20db9c65fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6cc1d509749ac3214d6bdfe8d02e1c91dcde89fc901e54c6019a451aba47c7592581eee63cf7dd0eea9a00f0776acca86d64850712929f6f29de9dadef95a6c
|
7
|
+
data.tar.gz: fd155b4e46710e57b0e95425ae896abdcb7a2efa7e0ddd872915156ffd2e92a0ef0933b433b0bfab0b8f399f46e500c7ee329bdb4c002a294dcef5d438a404b7
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -37,8 +37,14 @@ that you can configure any of these timing values, as explained later.
|
|
37
37
|
|
38
38
|
Or if you want to immediately receive `false` on an unsuccessful locking attempt, you can change the mutex mode to **non-blocking**.
|
39
39
|
|
40
|
-
|
41
|
-
|
40
|
+
Changelog
|
41
|
+
---------
|
42
|
+
|
43
|
+
### v3.0
|
44
|
+
|
45
|
+
* Ruby 2.0 or later is required.
|
46
|
+
|
47
|
+
### v2.0
|
42
48
|
|
43
49
|
* **Exception-based control flow**: Added `lock!` and `unlock!`, which raises an exception when fails to acquire a lock. Raises `Redis::Mutex::LockError` and `Redis::Mutex::UnlockError` respectively.
|
44
50
|
* **INCOMPATIBLE CHANGE**: `#lock` no longer accepts a block. Use `#with_lock` instead, which uses `lock!` internally and returns the value of block.
|
data/lib/redis/mutex/macro.rb
CHANGED
@@ -28,10 +28,18 @@ class Redis
|
|
28
28
|
if options[:after_failure].is_a?(Proc)
|
29
29
|
define_method(after_method, &options[:after_failure])
|
30
30
|
end
|
31
|
+
target_argument_names = instance_method(target.to_sym).parameters.map(&:last)
|
32
|
+
on_arguments = Array(options[:on])
|
33
|
+
mutex_arguments = on_arguments & target_argument_names
|
34
|
+
unknown_arguments = on_arguments - target_argument_names
|
35
|
+
if unknown_arguments.any?
|
36
|
+
raise ArgumentError, "You are trying to lock on unknown arguments: #{unknown_arguments.join(', ')}"
|
37
|
+
end
|
31
38
|
|
32
39
|
define_method(with_method) do |*args|
|
33
|
-
|
34
|
-
|
40
|
+
named_arguments = Hash[target_argument_names.zip(args)]
|
41
|
+
arguments = mutex_arguments.map { |name| named_arguments.fetch(name) }
|
42
|
+
key = self.class.name << '#' << target.to_s << ":" << arguments.join(':')
|
35
43
|
begin
|
36
44
|
Redis::Mutex.with_lock(key, options) do
|
37
45
|
send(without_method, *args)
|
data/redis-mutex.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
|
|
12
12
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
13
13
|
gem.name = "redis-mutex"
|
14
14
|
gem.require_paths = ["lib"]
|
15
|
-
gem.version = '
|
15
|
+
gem.version = '3.0.0' # retrieve this value by: Gem.loaded_specs['redis-mutex'].version.to_s
|
16
16
|
|
17
17
|
gem.add_runtime_dependency "redis-classy", "~> 1.2"
|
18
18
|
gem.add_development_dependency "rspec"
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class C
|
4
|
+
include Redis::Mutex::Macro
|
5
|
+
auto_mutex :run_singularly, :block => 0, :after_failure => lambda {|id| return "failure: #{id}" }
|
6
|
+
|
7
|
+
def run_singularly(id)
|
8
|
+
sleep 0.1
|
9
|
+
return "success: #{id}"
|
10
|
+
end
|
11
|
+
|
12
|
+
auto_mutex :run_singularly_on_args, :block => 0, :on => [:id, :bar], :after_failure => lambda {|id, *others| return "failure: #{id}" }
|
13
|
+
def run_singularly_on_args(id, foo, bar)
|
14
|
+
sleep 0.1
|
15
|
+
return "success: #{id}"
|
16
|
+
end
|
17
|
+
|
18
|
+
auto_mutex :run_singularly_on_keyword_args, :block => 0, :on => [:id, :bar], :after_failure => lambda {|id: 1, **others| return "failure: #{id}" }
|
19
|
+
def run_singularly_on_keyword_args(id: 1, foo: 1, bar: 1)
|
20
|
+
sleep 0.1
|
21
|
+
return "success: #{id}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe Redis::Mutex::Macro do
|
26
|
+
|
27
|
+
def race(a, b)
|
28
|
+
t1 = Thread.new(&a)
|
29
|
+
# In most cases t1 wins, but make sure to give it a head start,
|
30
|
+
# not exceeding the sleep inside the method.
|
31
|
+
sleep 0.01
|
32
|
+
t2 = Thread.new(&b)
|
33
|
+
t1.join
|
34
|
+
t2.join
|
35
|
+
end
|
36
|
+
|
37
|
+
let(:object_arg) { Object.new }
|
38
|
+
|
39
|
+
it 'adds auto_mutex' do
|
40
|
+
race(
|
41
|
+
proc { C.new.run_singularly(1).should == "success: 1" },
|
42
|
+
proc { C.new.run_singularly(2).should == "failure: 2" })
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'adds auto_mutex on different args' do
|
46
|
+
race(
|
47
|
+
proc { C.new.run_singularly_on_args(1, :'2', object_arg).should == "success: 1" },
|
48
|
+
proc { C.new.run_singularly_on_args(2, :'2', object_arg).should == "success: 2" })
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'adds auto_mutex on same args' do
|
52
|
+
race(
|
53
|
+
proc { C.new.run_singularly_on_args(1, :'2', object_arg).should == "success: 1" },
|
54
|
+
proc { C.new.run_singularly_on_args(1, :'2', object_arg).should == "failure: 1" })
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'adds auto_mutex on different keyword args' do
|
58
|
+
race(
|
59
|
+
proc { C.new.run_singularly_on_keyword_args(id: 1, foo: :'2', bar: object_arg).should == "success: 1" },
|
60
|
+
proc { C.new.run_singularly_on_keyword_args(id: 2, foo: :'2', bar: object_arg).should == "success: 2" })
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'adds auto_mutex on same keyword args' do
|
64
|
+
race(
|
65
|
+
proc { C.new.run_singularly_on_keyword_args(id: 1, foo: :'2', bar: object_arg).should == "success: 1" },
|
66
|
+
proc { C.new.run_singularly_on_keyword_args(id: 1, foo: :'2', bar: object_arg).should == "failure: 1" })
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'raise exception if there is no such argument' do
|
70
|
+
expect {
|
71
|
+
class C
|
72
|
+
auto_mutex :run_without_such_args, :block => 0, :on => [:missing_arg]
|
73
|
+
def run_without_such_args(id)
|
74
|
+
return "success: #{id}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
}.to raise_error(ArgumentError) { |error|
|
78
|
+
expect(error.message).to eq 'You are trying to lock on unknown arguments: missing_arg'
|
79
|
+
}
|
80
|
+
end
|
81
|
+
end
|
data/spec/redis_mutex_spec.rb
CHANGED
@@ -2,16 +2,6 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
SHORT_MUTEX_OPTIONS = { :block => 0.1, :sleep => 0.02 }
|
4
4
|
|
5
|
-
class C
|
6
|
-
include Redis::Mutex::Macro
|
7
|
-
auto_mutex :run_singularly, :block => 0, :after_failure => lambda {|id| return "failure: #{id}" }
|
8
|
-
|
9
|
-
def run_singularly(id)
|
10
|
-
sleep 0.1
|
11
|
-
return "success: #{id}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
5
|
describe Redis::Mutex do
|
16
6
|
before do
|
17
7
|
Redis::Classy.flushdb
|
@@ -160,18 +150,6 @@ describe Redis::Mutex do
|
|
160
150
|
Redis::Mutex.keys.size.should == 1
|
161
151
|
end
|
162
152
|
|
163
|
-
describe Redis::Mutex::Macro do
|
164
|
-
it 'adds auto_mutex' do
|
165
|
-
t1 = Thread.new { C.new.run_singularly(1).should == "success: 1" }
|
166
|
-
# In most cases t1 wins, but make sure to give it a head start,
|
167
|
-
# not exceeding the sleep inside the method.
|
168
|
-
sleep 0.01
|
169
|
-
t2 = Thread.new { C.new.run_singularly(2).should == "failure: 2" }
|
170
|
-
t1.join
|
171
|
-
t2.join
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
153
|
describe 'stress test' do
|
176
154
|
LOOP_NUM = 1000
|
177
155
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-mutex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenn Ejima
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-classy
|
@@ -84,6 +84,7 @@ files:
|
|
84
84
|
- lib/redis/mutex.rb
|
85
85
|
- lib/redis/mutex/macro.rb
|
86
86
|
- redis-mutex.gemspec
|
87
|
+
- spec/redis_mutex_macro_spec.rb
|
87
88
|
- spec/redis_mutex_spec.rb
|
88
89
|
- spec/spec_helper.rb
|
89
90
|
homepage: http://github.com/kenn/redis-mutex
|
@@ -105,10 +106,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
106
|
version: '0'
|
106
107
|
requirements: []
|
107
108
|
rubyforge_project:
|
108
|
-
rubygems_version: 2.0.
|
109
|
+
rubygems_version: 2.0.14
|
109
110
|
signing_key:
|
110
111
|
specification_version: 4
|
111
112
|
summary: Distrubuted mutex using Redis
|
112
113
|
test_files:
|
114
|
+
- spec/redis_mutex_macro_spec.rb
|
113
115
|
- spec/redis_mutex_spec.rb
|
114
116
|
- spec/spec_helper.rb
|