Class: Mongo::Lock
- Inherits:
-
Object
show all
- Defined in:
- lib/mongo-lock.rb,
lib/mongo-lock/version.rb,
lib/mongo-lock/configuration.rb
Defined Under Namespace
Classes: Configuration, NotAcquiredError, NotExtendedError, NotReleasedError
Constant Summary
collapse
- VERSION =
"1.0.0"
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(key, options = {}) ⇒ Lock
Returns a new instance of Lock.
95
96
97
98
99
|
# File 'lib/mongo-lock.rb', line 95
def initialize key, options = {}
self.configuration = Configuration.new self.class.configuration.to_hash, options
self.key = key
acquire_if_acquired
end
|
Instance Attribute Details
#acquired ⇒ Object
Returns the value of attribute acquired.
12
13
14
|
# File 'lib/mongo-lock.rb', line 12
def acquired
@acquired
end
|
#configuration ⇒ Object
Returns the value of attribute configuration.
10
11
12
|
# File 'lib/mongo-lock.rb', line 10
def configuration
@configuration
end
|
#expires_at ⇒ Object
Returns the value of attribute expires_at.
13
14
15
|
# File 'lib/mongo-lock.rb', line 13
def expires_at
@expires_at
end
|
#key ⇒ Object
Returns the value of attribute key.
11
12
13
|
# File 'lib/mongo-lock.rb', line 11
def key
@key
end
|
#released ⇒ Object
Returns the value of attribute released.
14
15
16
|
# File 'lib/mongo-lock.rb', line 14
def released
@released
end
|
Class Method Details
.acquire(key, options = {}) ⇒ Object
58
59
60
|
# File 'lib/mongo-lock.rb', line 58
def self.acquire key, options = {}
init_and_send key, options, :acquire
end
|
.acquire!(key, options = {}) ⇒ Object
66
67
68
|
# File 'lib/mongo-lock.rb', line 66
def self.acquire! key, options = {}
init_and_send key, options, :acquire!
end
|
.available?(key, options = {}) ⇒ Boolean
74
75
76
|
# File 'lib/mongo-lock.rb', line 74
def self.available? key, options = {}
init_and_send key, options, :available?
end
|
.clear_expired ⇒ Object
89
90
91
92
93
|
# File 'lib/mongo-lock.rb', line 89
def self.clear_expired
configuration.collections.each_pair do |key,collection|
collection.remove expires_at: { '$lt' => Time.now }
end
end
|
.configuration ⇒ Object
29
30
31
32
33
34
35
|
# File 'lib/mongo-lock.rb', line 29
def self.configuration
if defined? @@default_configuration
@@default_configuration
else
@@default_configuration = configure
end
end
|
16
17
18
19
20
21
22
23
24
25
26
27
|
# File 'lib/mongo-lock.rb', line 16
def self.configure options = {}, &block
defaults = {
timeout_in: 10,
limit: 100,
frequency: 1,
expires_after: 10,
raise: false,
owner: Proc.new { "#{`hostname`.strip}:#{Process.pid}:#{Thread.object_id}" }
}
defaults = defaults.merge(@@default_configuration) if defined?(@@default_configuration) && @@default_configuration
@@default_configuration = Configuration.new(defaults, options, &block)
end
|
.ensure_indexes ⇒ Object
78
79
80
81
82
83
84
85
86
87
|
# File 'lib/mongo-lock.rb', line 78
def self.ensure_indexes
configuration.collections.each_pair do |key, collection|
collection.create_index([
['key', Mongo::ASCENDING],
['owner', Mongo::ASCENDING],
['expires_at', Mongo::ASCENDING]
])
collection.create_index([['ttl', Mongo::ASCENDING]],{ expireAfterSeconds: 0 })
end
end
|
.init_and_send(key, options = {}, method) ⇒ Object
52
53
54
55
56
|
# File 'lib/mongo-lock.rb', line 52
def self.init_and_send key, options = {}, method
lock = self.new(key, options)
lock.send(method)
lock
end
|
.release(key, options = {}) ⇒ Object
62
63
64
|
# File 'lib/mongo-lock.rb', line 62
def self.release key, options = {}
init_and_send key, options, :release
end
|
.release!(key, options = {}) ⇒ Object
70
71
72
|
# File 'lib/mongo-lock.rb', line 70
def self.release! key, options = {}
init_and_send key, options, :release!
end
|
.release_all(options = {}) ⇒ Object
37
38
39
40
41
42
43
44
45
|
# File 'lib/mongo-lock.rb', line 37
def self.release_all options = {}
if options.include? :collection
release_collection configuration.collection(options[:collection]), options[:owner]
else
configuration.collections.each_pair do |key,collection|
release_collection collection, options[:owner]
end
end
end
|
.release_collection(collection, owner = nil) ⇒ Object
47
48
49
50
|
# File 'lib/mongo-lock.rb', line 47
def self.release_collection collection, owner=nil
selector = if owner then { owner: owner } else {} end
collection.remove(selector)
end
|
Instance Method Details
#acquire(options = {}) ⇒ Object
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
# File 'lib/mongo-lock.rb', line 106
def acquire options = {}
options = configuration.to_hash.merge options
i = 1
time_spent = 0
loop do
if options[:timeout_in] && options[:timeout_in] < time_spent
return raise_or_false options
elsif options[:limit] && options[:limit] < i
return raise_or_false options
elsif existing_lock = find_or_insert(options)
if existing_lock['owner'] == options[:owner]
self.acquired = true
extend_by options[:expires_after]
return true
end
else
self.acquired = true
return true
end
if options[:frequency].is_a? Proc
frequency = options[:frequency].call(i)
else
frequency = options[:frequency]
end
sleep frequency
time_spent += frequency
i += 1
end
end
|
#acquire!(options = {}) ⇒ Object
148
149
150
151
|
# File 'lib/mongo-lock.rb', line 148
def acquire! options = {}
options[:raise] = true
acquire options
end
|
#acquire_if_acquired ⇒ Object
285
286
287
288
289
290
291
292
293
|
# File 'lib/mongo-lock.rb', line 285
def acquire_if_acquired
if (collection.find({
key: key,
owner: configuration.owner,
expires_at: { '$gt' => Time.now }
}).count > 0)
self.acquired = true
end
end
|
#acquired? ⇒ Boolean
273
274
275
|
# File 'lib/mongo-lock.rb', line 273
def acquired?
!!acquired && !expired?
end
|
#available?(options = {}) ⇒ Boolean
260
261
262
263
264
|
# File 'lib/mongo-lock.rb', line 260
def available? options = {}
options = configuration.to_hash.merge options
existing_lock = collection.find(query).first
!existing_lock || existing_lock['owner'] == options[:owner]
end
|
101
102
103
104
|
# File 'lib/mongo-lock.rb', line 101
def configure options = {}, &block
self.configuration = Configuration.new self.configuration.to_hash, options
yield self.configuration if block_given?
end
|
#expired? ⇒ Boolean
277
278
279
|
# File 'lib/mongo-lock.rb', line 277
def expired?
!!(expires_at && expires_at < Time.now)
end
|
#extend(options = {}) ⇒ Object
245
246
247
248
|
# File 'lib/mongo-lock.rb', line 245
def extend options = {}
time = configuration.to_hash.merge(options)[:expires_after]
extend_by time, options
end
|
#extend!(options = {}) ⇒ Object
255
256
257
258
|
# File 'lib/mongo-lock.rb', line 255
def extend! options = {}
options[:raise] = true
extend options
end
|
#extend_by(time, options = {}) ⇒ Object
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
|
# File 'lib/mongo-lock.rb', line 216
def extend_by time, options = {}
options = configuration.to_hash.merge options
if !acquired?
return raise_or_false options, NotExtendedError
elsif expired?
return raise_or_false options, NotExtendedError
else
to_expire_at = expires_at + time
existing_lock = collection.find_and_modify({
query: query,
update: {
'$set' => {
key: key,
owner: options[:owner],
expires_at: to_expire_at,
ttl: to_expire_at
}
},
upsert: true
})
true
end
end
|
#extend_by!(time, options = {}) ⇒ Object
250
251
252
253
|
# File 'lib/mongo-lock.rb', line 250
def extend_by! time, options = {}
options[:raise] = true
extend_by time, options
end
|
#find_or_insert(options) ⇒ Object
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
# File 'lib/mongo-lock.rb', line 192
def find_or_insert options
to_expire_at = Time.now + options[:expires_after]
existing_lock = collection.find_and_modify({
query: query,
update: {
'$setOnInsert' => {
key: key,
owner: options[:owner],
expires_at: to_expire_at,
ttl: to_expire_at
}
},
upsert: true
})
if existing_lock
self.expires_at = existing_lock['expires_at']
else
self.expires_at = to_expire_at
end
existing_lock
end
|
#query ⇒ Object
266
267
268
269
270
271
|
# File 'lib/mongo-lock.rb', line 266
def query
{
key: key,
expires_at: { '$gt' => Time.now }
}
end
|
#raise_or_false(options, error = NotAcquiredError) ⇒ Object
187
188
189
190
|
# File 'lib/mongo-lock.rb', line 187
def raise_or_false options, error = NotAcquiredError
raise error if options[:raise]
false
end
|
#release(options = {}) ⇒ Object
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
# File 'lib/mongo-lock.rb', line 153
def release options = {}
options = configuration.to_hash.merge options
if released?
return true
elsif expired?
self.released = true
self.acquired = false
return true
elsif !acquired?
if acquire options.merge(raise: false)
return release options
else
return raise_or_false options, NotReleasedError
end
else
self.released = true
self.acquired = false
collection.remove key: key, owner: options[:owner]
return true
end
end
|
#release!(options = {}) ⇒ Object
182
183
184
185
|
# File 'lib/mongo-lock.rb', line 182
def release! options = {}
options[:raise] = true
release options
end
|
#released? ⇒ Boolean
281
282
283
|
# File 'lib/mongo-lock.rb', line 281
def released?
!!released
end
|