Class: Offshore::Mutex
- Inherits:
-
Object
show all
- Defined in:
- lib/offshore/server/mutex.rb
Overview
Options
:block => Specify in seconds how long you want to wait for the lock to be released. Speficy 0
if you need non-blocking sematics and return false immediately. (default: 1)
:sleep => Specify in seconds how long the polling interval should be when :block is given.
It is recommended that you do NOT go below 0.01. (default: 0.1)
:expire => Specify in seconds when the lock should forcibly be removed when something went wrong
with the one who held the lock. (default: 10)
Constant Summary
collapse
- DEFAULT_EXPIRE =
10*60*1000
- LockError =
Class.new(StandardError)
- UnlockError =
Class.new(StandardError)
- AssertionError =
Class.new(StandardError)
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(object, options = {}) ⇒ Mutex
Returns a new instance of Mutex.
24
25
26
27
28
29
|
# File 'lib/offshore/server/mutex.rb', line 24
def initialize(object, options={})
@key = (object.is_a?(String) || object.is_a?(Symbol) ? object.to_s : "#{object.class.name}:#{object.id}")
@block = options[:block] || 0 @sleep = options[:sleep] || 0.1
@expire = options[:expire] || DEFAULT_EXPIRE
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(command, *args, &block) ⇒ Object
32
33
34
|
# File 'lib/offshore/server/mutex.rb', line 32
def method_missing(command, *args, &block)
self.class.send(command, @key, *args, &block)
end
|
Instance Attribute Details
#key ⇒ Object
Returns the value of attribute key.
23
24
25
|
# File 'lib/offshore/server/mutex.rb', line 23
def key
@key
end
|
Class Method Details
.db ⇒ Object
100
101
102
|
# File 'lib/offshore/server/mutex.rb', line 100
def db
Offshore.redis
end
|
.lock(object, options = {}) ⇒ Object
126
127
128
129
|
# File 'lib/offshore/server/mutex.rb', line 126
def lock(object, options = {})
raise_assertion_error if block_given?
new(object, options).lock
end
|
.lock!(object, options = {}) ⇒ Object
136
137
138
|
# File 'lib/offshore/server/mutex.rb', line 136
def lock!(object, options = {})
new(object, options).lock!
end
|
.method_missing(command, *args, &block) ⇒ Object
104
105
106
|
# File 'lib/offshore/server/mutex.rb', line 104
def method_missing(command, *args, &block)
db.send(command, *args, &block)
end
|
.raise_assertion_error ⇒ Object
149
150
151
|
# File 'lib/offshore/server/mutex.rb', line 149
def raise_assertion_error
raise AssertionError, 'block syntax has been removed from #lock, use #with_lock instead'
end
|
.sweep ⇒ Object
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
# File 'lib/offshore/server/mutex.rb', line 108
def sweep
return 0 if (all_keys = keys).empty?
now = Time.now.to_f
values = mget(*all_keys)
expired_keys = all_keys.zip(values).select do |key, time|
time && time.to_f <= now
end
expired_keys.each do |key, _|
del(key) if getset(key, now + DEFAULT_EXPIRE).to_f <= now
end
expired_keys.size
end
|
.unlock(object, options = {}) ⇒ Object
131
132
133
134
|
# File 'lib/offshore/server/mutex.rb', line 131
def unlock(object, options = {})
raise_assertion_error if block_given?
new(object, options).unlock
end
|
.unlock!(object, options = {}) ⇒ Object
140
141
142
143
|
# File 'lib/offshore/server/mutex.rb', line 140
def unlock!(object, options = {})
raise_assertion_error if block_given?
new(object, options).unlock!
end
|
.with_lock(object, options = {}, &block) ⇒ Object
145
146
147
|
# File 'lib/offshore/server/mutex.rb', line 145
def with_lock(object, options = {}, &block)
new(object, options).with_lock(&block)
end
|
Instance Method Details
#lock ⇒ Object
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
# File 'lib/offshore/server/mutex.rb', line 36
def lock
self.class.raise_assertion_error if block_given?
@locking = false
if @block > 0
start_at = Time.now
while Time.now - start_at < @block
@locking = true and break if try_lock
sleep @sleep
end
else
@locking = try_lock
end
@locking
end
|
#lock! ⇒ Object
91
92
93
|
# File 'lib/offshore/server/mutex.rb', line 91
def lock!
lock or raise LockError, "failed to acquire lock #{key.inspect}"
end
|
#try_lock ⇒ Object
54
55
56
57
58
59
60
61
62
63
|
# File 'lib/offshore/server/mutex.rb', line 54
def try_lock
now = Time.now.to_f
@expires_at = now + @expire return true if setnx(@expires_at) return false if get.to_f > now
return true if getset(@expires_at).to_f <= now return false end
|
#unlock(force = false) ⇒ Object
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# File 'lib/offshore/server/mutex.rb', line 65
def unlock(force = false)
force = true
if force
!!del
else
false
end
end
|
#unlock!(force = false) ⇒ Object
95
96
97
|
# File 'lib/offshore/server/mutex.rb', line 95
def unlock!(force = false)
unlock(force) or raise UnlockError, "failed to release lock #{key.inspect}"
end
|
#with_lock ⇒ Object
80
81
82
83
84
85
86
87
88
89
|
# File 'lib/offshore/server/mutex.rb', line 80
def with_lock
if lock!
begin
@result = yield
ensure
unlock
end
end
@result
end
|