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.
@@ -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
- if other_lock = Lock.find(cache_key)
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
- [ pid, thread_object_id ]
73
+ []
97
74
  end
98
75
 
99
76
  def marshal_load(source)
100
- @pid, @thread_object_id = source
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
@@ -1,3 +1,3 @@
1
1
  module LockMethod
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
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. TTL in seconds, defaults to whatever's in LockMethod.config.default_ttl
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(method_id, ttl = nil)
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 |*args|
56
- lock = ::LockMethod::Lock.new self, method_id, :ttl => ttl, :args => args
57
- lock.call_and_lock original_method_id, *args
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
@@ -74,6 +74,16 @@ module BlogM
74
74
  end
75
75
  end
76
76
 
77
+ module BlogSpin
78
+ def self.get_latest_entries
79
+ sleep 2
80
+ 'danke schoen'
81
+ end
82
+ class << self
83
+ lock_method :get_latest_entries, :spin => true
84
+ end
85
+ end
86
+
77
87
  class Test::Unit::TestCase
78
88
 
79
89
  end
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.2.1
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-06 00:00:00.000000000Z
12
+ date: 2011-12-12 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cache
16
- requirement: &2161845800 !ruby/object:Gem::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: *2161845800
24
+ version_requirements: *2153961100
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activesupport
27
- requirement: &2161843720 !ruby/object:Gem::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: *2161843720
35
+ version_requirements: *2153960680
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: test-unit
38
- requirement: &2161841860 !ruby/object:Gem::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: *2161841860
46
+ version_requirements: *2153960220
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: memcached
49
- requirement: &2161830720 !ruby/object:Gem::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: *2161830720
57
+ version_requirements: *2153959800
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: redis
60
- requirement: &2161830100 !ruby/object:Gem::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: *2161830100
68
+ version_requirements: *2153959380
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: ruby-debug19
71
- requirement: &2161829520 !ruby/object:Gem::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: *2161829520
79
+ version_requirements: *2153958940
80
80
  description: Like alias_method, but it's lock_method!
81
81
  email:
82
82
  - seamus@abshere.net