lock_method 0.2.1 → 0.3.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.
- data/lib/lock_method/lock.rb +12 -32
- data/lib/lock_method/version.rb +1 -1
- data/lib/lock_method.rb +16 -5
- data/test/helper.rb +10 -0
- data/test/shared_tests.rb +9 -42
- metadata +14 -14
data/lib/lock_method/lock.rb
CHANGED
@@ -14,16 +14,6 @@ module LockMethod
|
|
14
14
|
def method_signature(obj, method_id)
|
15
15
|
[ klass_name(obj), method_id ].join method_delimiter(obj)
|
16
16
|
end
|
17
|
-
def process_alive?(pid)
|
18
|
-
::Process.kill 0, pid
|
19
|
-
rescue ::Errno::ESRCH
|
20
|
-
false
|
21
|
-
end
|
22
|
-
def thread_alive?(thread_object_id)
|
23
|
-
if thr = ::Thread.list.detect { |t| t.object_id == thread_object_id }
|
24
|
-
thr.status == 'sleep' or thr.status == 'run'
|
25
|
-
end
|
26
|
-
end
|
27
17
|
end
|
28
18
|
|
29
19
|
attr_reader :obj
|
@@ -36,8 +26,13 @@ module LockMethod
|
|
36
26
|
options = options.symbolize_keys
|
37
27
|
@ttl = options[:ttl]
|
38
28
|
@args = options[:args]
|
29
|
+
@spin = options[:spin]
|
39
30
|
end
|
40
|
-
|
31
|
+
|
32
|
+
def spin?
|
33
|
+
@spin == true
|
34
|
+
end
|
35
|
+
|
41
36
|
def method_signature
|
42
37
|
@method_signature ||= Lock.method_signature(obj, method_id)
|
43
38
|
end
|
@@ -46,14 +41,6 @@ module LockMethod
|
|
46
41
|
@ttl ||= Config.instance.default_ttl
|
47
42
|
end
|
48
43
|
|
49
|
-
def pid
|
50
|
-
@pid ||= ::Process.pid
|
51
|
-
end
|
52
|
-
|
53
|
-
def thread_object_id
|
54
|
-
@thread_object_id ||= ::Thread.current.object_id
|
55
|
-
end
|
56
|
-
|
57
44
|
def obj_hash
|
58
45
|
@obj_hash ||= obj.respond_to?(:method_lock_hash) ? obj.method_lock_hash : obj.hash
|
59
46
|
end
|
@@ -71,9 +58,7 @@ module LockMethod
|
|
71
58
|
end
|
72
59
|
|
73
60
|
def locked?
|
74
|
-
|
75
|
-
other_lock.process_and_thread_still_alive?
|
76
|
-
end
|
61
|
+
!!Lock.find(cache_key)
|
77
62
|
end
|
78
63
|
|
79
64
|
def cache_key
|
@@ -84,23 +69,18 @@ module LockMethod
|
|
84
69
|
end
|
85
70
|
end
|
86
71
|
|
87
|
-
def process_and_thread_still_alive?
|
88
|
-
if pid == ::Process.pid
|
89
|
-
Lock.thread_alive? thread_object_id
|
90
|
-
else
|
91
|
-
Lock.process_alive? pid
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
72
|
def marshal_dump
|
96
|
-
[
|
73
|
+
[]
|
97
74
|
end
|
98
75
|
|
99
76
|
def marshal_load(source)
|
100
|
-
|
77
|
+
# nothing
|
101
78
|
end
|
102
79
|
|
103
80
|
def call_and_lock(*original_method_id_and_args)
|
81
|
+
until !spin? or !locked?
|
82
|
+
::Kernel.sleep 0.5
|
83
|
+
end
|
104
84
|
if locked?
|
105
85
|
raise Locked
|
106
86
|
else
|
data/lib/lock_method/version.rb
CHANGED
data/lib/lock_method.rb
CHANGED
@@ -34,7 +34,11 @@ module LockMethod
|
|
34
34
|
|
35
35
|
# All Classes (but not instances), get the <tt>.lock_method</tt> method.
|
36
36
|
module ClassMethods
|
37
|
-
# Lock a method.
|
37
|
+
# Lock a method.
|
38
|
+
#
|
39
|
+
# Options:
|
40
|
+
# * <tt>:ttl</tt> TTL in seconds, defaults to whatever's in LockMethod.config.default_ttl
|
41
|
+
# * <tt>:spin</tt> Whether to wait indefinitely for another lock to expire
|
38
42
|
#
|
39
43
|
# Note 2: Check out LockMethod.config.default_ttl... the default is 24 hours!
|
40
44
|
#
|
@@ -49,12 +53,19 @@ module LockMethod
|
|
49
53
|
# # if you wanted a different ttl...
|
50
54
|
# # lock_method :get_latest_entries, 800 #seconds
|
51
55
|
# end
|
52
|
-
def lock_method(
|
56
|
+
def lock_method(*args)
|
57
|
+
options = args.extract_options!
|
58
|
+
options = options.symbolize_keys
|
59
|
+
method_id = args.first
|
60
|
+
if args.last.is_a?(::Numeric)
|
61
|
+
options[:ttl] ||= args.last
|
62
|
+
end
|
53
63
|
original_method_id = "_unlocked_#{method_id}"
|
54
64
|
alias_method original_method_id, method_id
|
55
|
-
define_method method_id do |*
|
56
|
-
|
57
|
-
lock.
|
65
|
+
define_method method_id do |*args1|
|
66
|
+
options = options.merge(:args => args1)
|
67
|
+
lock = ::LockMethod::Lock.new self, method_id, options
|
68
|
+
lock.call_and_lock original_method_id, *args1
|
58
69
|
end
|
59
70
|
end
|
60
71
|
end
|
data/test/helper.rb
CHANGED
data/test/shared_tests.rb
CHANGED
@@ -48,48 +48,6 @@ module SharedTests
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def test_04_locked_by_SIGKILLed_process
|
52
|
-
pid = Kernel.fork { Blog2.get_latest_entries }
|
53
|
-
|
54
|
-
# give it a bit of time to lock
|
55
|
-
sleep 1
|
56
|
-
|
57
|
-
# the blocker won't have finished
|
58
|
-
assert_raises(LockMethod::Locked) do
|
59
|
-
Blog2.get_latest_entries
|
60
|
-
end
|
61
|
-
|
62
|
-
# kill it and then wait for it to be reaped
|
63
|
-
Process.detach pid
|
64
|
-
Process.kill 9, pid
|
65
|
-
sleep 1
|
66
|
-
|
67
|
-
# now we're sure
|
68
|
-
assert_nothing_raised do
|
69
|
-
Blog2.get_latest_entries
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def test_05_locked_by_killed_thread
|
74
|
-
blocker = Thread.new { Blog2.get_latest_entries }
|
75
|
-
|
76
|
-
# give it a bit of time to lock
|
77
|
-
sleep 1
|
78
|
-
|
79
|
-
# the blocker won't have finished
|
80
|
-
assert_raises(LockMethod::Locked) do
|
81
|
-
Blog2.get_latest_entries
|
82
|
-
end
|
83
|
-
|
84
|
-
# kinda like a SIGKILL
|
85
|
-
blocker.kill
|
86
|
-
|
87
|
-
# now we're sure
|
88
|
-
assert_nothing_raised do
|
89
|
-
Blog2.get_latest_entries
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
51
|
def test_06_locked_by_normally_finishing_thread
|
94
52
|
blocker = Thread.new { Blog2.get_latest_entries }
|
95
53
|
|
@@ -239,4 +197,13 @@ module SharedTests
|
|
239
197
|
Encoding.default_internal = old_int
|
240
198
|
Encoding.default_external = old_ext
|
241
199
|
end
|
200
|
+
|
201
|
+
def test_14_spin
|
202
|
+
pid = Kernel.fork { BlogSpin.get_latest_entries }
|
203
|
+
|
204
|
+
# give it a bit of time to lock
|
205
|
+
sleep 1
|
206
|
+
|
207
|
+
assert_equal 'danke schoen', BlogSpin.get_latest_entries
|
208
|
+
end
|
242
209
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lock_method
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-12-
|
12
|
+
date: 2011-12-12 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cache
|
16
|
-
requirement: &
|
16
|
+
requirement: &2153961100 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.2.1
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2153961100
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: activesupport
|
27
|
-
requirement: &
|
27
|
+
requirement: &2153960680 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2153960680
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: test-unit
|
38
|
-
requirement: &
|
38
|
+
requirement: &2153960220 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2153960220
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: memcached
|
49
|
-
requirement: &
|
49
|
+
requirement: &2153959800 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2153959800
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: redis
|
60
|
-
requirement: &
|
60
|
+
requirement: &2153959380 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2153959380
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: ruby-debug19
|
71
|
-
requirement: &
|
71
|
+
requirement: &2153958940 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *2153958940
|
80
80
|
description: Like alias_method, but it's lock_method!
|
81
81
|
email:
|
82
82
|
- seamus@abshere.net
|