resque-lock-timeout 0.3.3 → 0.4.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/HISTORY.md +7 -3
- data/README.md +26 -2
- data/lib/resque/plugins/lock_timeout.rb +113 -26
- data/test/lock_test.rb +38 -1
- data/test/redis-test.conf +8 -8
- data/test/test_helper.rb +20 -17
- data/test/test_jobs.rb +34 -1
- metadata +53 -18
data/HISTORY.md
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
## 0.4.0 (2012-11-09)
|
2
|
+
|
3
|
+
* Add `@loner` boolean option to prevent job being enqueued if already
|
4
|
+
running/enqueued. (Thanks to @ssaunier)
|
5
|
+
|
1
6
|
## 0.3.3 (2012-03-09)
|
2
|
-
## 0.3.2 (2012-03-09)
|
3
7
|
|
4
|
-
*
|
8
|
+
* Tested against v1.20.0 of resque.
|
5
9
|
|
6
10
|
## 0.3.1 (2011-07-16)
|
7
11
|
|
@@ -23,4 +27,4 @@
|
|
23
27
|
## 0.2.0 (2010-05-05)
|
24
28
|
|
25
29
|
* Initial release as `resque-lock-timeout`, forked from Chris Wanstrath'
|
26
|
-
`resque-lock`.
|
30
|
+
`resque-lock`.
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ A [Resque][rq] plugin. Requires Resque >= v1.8.0.
|
|
6
6
|
resque-lock-timeout adds locking, with optional timeout/deadlock handling to
|
7
7
|
resque jobs.
|
8
8
|
|
9
|
-
Using a `lock_timeout` allows you to re-
|
9
|
+
Using a `lock_timeout` allows you to re-acquire the lock should your worker
|
10
10
|
fail, crash, or is otherwise unable to relase the lock. **i.e.** Your server
|
11
11
|
unexpectedly looses power. Very handy for jobs that are recurring or may be
|
12
12
|
retried.
|
@@ -37,7 +37,23 @@ Default behaviour...
|
|
37
37
|
|
38
38
|
Please see below for more information about the identifer/lock key.
|
39
39
|
|
40
|
-
###
|
40
|
+
### Enqueued Exclusivity (Loner Option)
|
41
|
+
|
42
|
+
Setting the `@loner` boolean to `true` will ensure the job is not enqueued if
|
43
|
+
the job (identified by the `identifier` method) is already running/enqueued.
|
44
|
+
|
45
|
+
class LonelyJob
|
46
|
+
extend Resque::Plugins::LockTimeout
|
47
|
+
@queue = :loners
|
48
|
+
|
49
|
+
@loner = true
|
50
|
+
|
51
|
+
def self.perform(repo_id)
|
52
|
+
heavy_lifting
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
### Lock Expiry/Timeout
|
41
57
|
|
42
58
|
The locking algorithm used can be found in the [Redis SETNX][redis-setnx]
|
43
59
|
documentation.
|
@@ -158,11 +174,19 @@ Several callbacks are available to override and implement your own logic, e.g.
|
|
158
174
|
# Lock may be held for upto an hour.
|
159
175
|
@lock_timeout = 3600
|
160
176
|
|
177
|
+
# No same job get enqueued if one already running/enqueued
|
178
|
+
@loner = true
|
179
|
+
|
161
180
|
# Job failed to acquire lock. You may implement retry or other logic.
|
162
181
|
def self.lock_failed(repo_id)
|
163
182
|
raise LockFailed
|
164
183
|
end
|
165
184
|
|
185
|
+
# Unable to enqueue job because its running or already enqueued.
|
186
|
+
def self.loner_enqueue_failed(repo_id)
|
187
|
+
raise EnqueueFailed
|
188
|
+
end
|
189
|
+
|
166
190
|
# Job has complete; but the lock expired before we could relase it.
|
167
191
|
# The lock wasn't released; as its *possible* the lock is now held
|
168
192
|
# by another job.
|
@@ -3,32 +3,51 @@ module Resque
|
|
3
3
|
# If you want only one instance of your job running at a time,
|
4
4
|
# extend it with this module:
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# require 'resque-lock-timeout'
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
8
|
+
# class UpdateNetworkGraph
|
9
|
+
# extend Resque::Plugins::LockTimeout
|
10
|
+
# @queue = :network_graph
|
11
11
|
#
|
12
|
-
#
|
13
|
-
#
|
12
|
+
# def self.perform(repo_id)
|
13
|
+
# heavy_lifting
|
14
|
+
# end
|
14
15
|
# end
|
15
|
-
# end
|
16
16
|
#
|
17
|
-
# If you wish to limit the
|
17
|
+
# If you wish to limit the duration a lock may be held for, you can
|
18
18
|
# set/override `lock_timeout`. e.g.
|
19
19
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
20
|
+
# class UpdateNetworkGraph
|
21
|
+
# extend Resque::Plugins::LockTimeout
|
22
|
+
# @queue = :network_graph
|
23
23
|
#
|
24
|
-
#
|
25
|
-
#
|
24
|
+
# # lock may be held for upto an hour.
|
25
|
+
# @lock_timeout = 3600
|
26
26
|
#
|
27
|
-
#
|
28
|
-
#
|
27
|
+
# def self.perform(repo_id)
|
28
|
+
# heavy_lifting
|
29
|
+
# end
|
29
30
|
# end
|
30
|
-
# end
|
31
31
|
#
|
32
|
+
# If you wish that only one instance of the job defined by #identifier may be
|
33
|
+
# enqueued or running, you can set/override `loner`. e.g.
|
34
|
+
#
|
35
|
+
# class PdfExport
|
36
|
+
# extend Resque::Plugins::LockTimeout
|
37
|
+
# @queue = :exports
|
38
|
+
#
|
39
|
+
# # only one job can be running/enqueued at a time. For instance a button
|
40
|
+
# # to run a PDF export. If the user clicks several times on it, enqueue
|
41
|
+
# # the job if and only if
|
42
|
+
# # - the same export is not currently running
|
43
|
+
# # - the same export is not currently queued.
|
44
|
+
# # ('same' being defined by `identifier`)
|
45
|
+
# @loner = true
|
46
|
+
#
|
47
|
+
# def self.perform(repo_id)
|
48
|
+
# heavy_lifting
|
49
|
+
# end
|
50
|
+
# end
|
32
51
|
module LockTimeout
|
33
52
|
# @abstract You may override to implement a custom identifier,
|
34
53
|
# you should consider doing this if your job arguments
|
@@ -56,8 +75,7 @@ module Resque
|
|
56
75
|
# Override to fully control the lock key used. It is passed
|
57
76
|
# the job arguments.
|
58
77
|
#
|
59
|
-
# The default looks like this:
|
60
|
-
# `resque-lock-timeout:<class name>:<identifier>`
|
78
|
+
# The default looks like this: `lock:<class name>:<identifier>`
|
61
79
|
#
|
62
80
|
# @param [Array] args job arguments
|
63
81
|
# @return [String] redis key
|
@@ -65,6 +83,16 @@ module Resque
|
|
65
83
|
['lock', name, identifier(*args)].compact.join(':')
|
66
84
|
end
|
67
85
|
|
86
|
+
# Builds lock key used by `@loner` option. Passed job arguments.
|
87
|
+
#
|
88
|
+
# The default looks like this: `loner:lock:<class name>:<identifier>`
|
89
|
+
#
|
90
|
+
# @param [Array] args job arguments
|
91
|
+
# @return [String] redis key
|
92
|
+
def redis_loner_lock_key(*args)
|
93
|
+
['loner', redis_lock_key(*args)].compact.join(':')
|
94
|
+
end
|
95
|
+
|
68
96
|
# Number of seconds the lock may be held for.
|
69
97
|
# A value of 0 or below will lock without a timeout.
|
70
98
|
#
|
@@ -74,6 +102,14 @@ module Resque
|
|
74
102
|
@lock_timeout ||= 0
|
75
103
|
end
|
76
104
|
|
105
|
+
# Whether one instance of the job should be running or enqueued.
|
106
|
+
#
|
107
|
+
# @param [Array] args job arguments
|
108
|
+
# @return [TrueClass || FalseClass]
|
109
|
+
def loner(*args)
|
110
|
+
@loner ||= false
|
111
|
+
end
|
112
|
+
|
77
113
|
# Convenience method, not used internally.
|
78
114
|
#
|
79
115
|
# @return [Boolean] true if the job is locked by someone
|
@@ -82,12 +118,19 @@ module Resque
|
|
82
118
|
end
|
83
119
|
|
84
120
|
# @abstract
|
85
|
-
# Hook method; called when a were unable to
|
121
|
+
# Hook method; called when a were unable to acquire the lock.
|
86
122
|
#
|
87
123
|
# @param [Array] args job arguments
|
88
124
|
def lock_failed(*args)
|
89
125
|
end
|
90
126
|
|
127
|
+
# @abstract
|
128
|
+
# Hook method; called when a were unable to enqueue loner job.
|
129
|
+
#
|
130
|
+
# @param [Array] args job arguments
|
131
|
+
def loner_enqueue_failed(*args)
|
132
|
+
end
|
133
|
+
|
91
134
|
# @abstract
|
92
135
|
# Hook method; called when the lock expired before we released it.
|
93
136
|
#
|
@@ -95,17 +138,49 @@ module Resque
|
|
95
138
|
def lock_expired_before_release(*args)
|
96
139
|
end
|
97
140
|
|
98
|
-
#
|
141
|
+
# @abstract
|
142
|
+
# if the job is a `loner`, enqueue only if no other same job
|
143
|
+
# is already running/enqueued
|
99
144
|
#
|
100
|
-
#
|
145
|
+
# @param [Array] args job arguments
|
146
|
+
def before_enqueue_lock(*args)
|
147
|
+
if loner
|
148
|
+
if locked?(*args)
|
149
|
+
# Same job is currently running
|
150
|
+
loner_enqueue_failed(*args)
|
151
|
+
false
|
152
|
+
else
|
153
|
+
acquire_loner_lock!(*args)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Try to acquire a lock for running the job.
|
159
|
+
# @return [Boolean, Fixnum]
|
160
|
+
def acquire_lock!(*args)
|
161
|
+
acquire_lock_impl!(:redis_lock_key, :lock_failed, *args)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Try to acquire a lock to enqueue a loner job.
|
165
|
+
# @return [Boolean, Fixnum]
|
166
|
+
def acquire_loner_lock!(*args)
|
167
|
+
acquire_lock_impl!(:redis_loner_lock_key, :loner_enqueue_failed, *args)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Generic implementation of the locking logic
|
171
|
+
#
|
172
|
+
# Returns false; when unable to acquire the lock.
|
101
173
|
# * Returns true; when lock acquired, without a timeout.
|
102
174
|
# * Returns timestamp; when lock acquired with a timeout, timestamp is
|
103
175
|
# when the lock timeout expires.
|
104
176
|
#
|
177
|
+
# @param [Symbol] lock_key_method the method returning redis key to lock
|
178
|
+
# @param [Symbol] failed_hook the method called if lock failed
|
179
|
+
# @param [Array] args job arguments
|
105
180
|
# @return [Boolean, Fixnum]
|
106
|
-
def
|
181
|
+
def acquire_lock_impl!(lock_key_method, failed_hook, *args)
|
107
182
|
acquired = false
|
108
|
-
lock_key =
|
183
|
+
lock_key = self.send lock_key_method, *args
|
109
184
|
|
110
185
|
unless lock_timeout(*args) > 0
|
111
186
|
# Acquire without using a timeout.
|
@@ -115,11 +190,11 @@ module Resque
|
|
115
190
|
acquired, lock_until = acquire_lock_algorithm!(lock_key, *args)
|
116
191
|
end
|
117
192
|
|
118
|
-
|
193
|
+
self.send(failed_hook, *args) if !acquired
|
119
194
|
lock_until && acquired ? lock_until : acquired
|
120
195
|
end
|
121
196
|
|
122
|
-
# Attempts to
|
197
|
+
# Attempts to acquire the lock using a timeout / deadlock algorithm.
|
123
198
|
#
|
124
199
|
# Locking algorithm: http://code.google.com/p/redis/wiki/SetnxCommand
|
125
200
|
#
|
@@ -154,6 +229,13 @@ module Resque
|
|
154
229
|
lock_redis.del(redis_lock_key(*args))
|
155
230
|
end
|
156
231
|
|
232
|
+
# Release the enqueue lock for loner jobs
|
233
|
+
#
|
234
|
+
# @param [Array] args job arguments
|
235
|
+
def release_loner_lock!(*args)
|
236
|
+
lock_redis.del(redis_loner_lock_key(*args))
|
237
|
+
end
|
238
|
+
|
157
239
|
# Refresh the lock.
|
158
240
|
#
|
159
241
|
# @param [Array] args job arguments
|
@@ -167,8 +249,13 @@ module Resque
|
|
167
249
|
#
|
168
250
|
# @param [Array] args job arguments
|
169
251
|
def around_perform_lock(*args)
|
252
|
+
lock_until = acquire_lock!(*args)
|
253
|
+
|
254
|
+
# Release loner lock as job has been dequeued
|
255
|
+
release_loner_lock!(*args) if loner
|
256
|
+
|
170
257
|
# Abort if another job holds the lock.
|
171
|
-
return unless lock_until
|
258
|
+
return unless lock_until
|
172
259
|
|
173
260
|
begin
|
174
261
|
yield
|
data/test/lock_test.rb
CHANGED
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/test_helper'
|
|
2
2
|
|
3
3
|
class LockTest < MiniTest::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
$success = $lock_failed = $lock_expired = 0
|
5
|
+
$success = $lock_failed = $lock_expired = $enqueue_failed = 0
|
6
6
|
Resque.redis.flushall
|
7
7
|
@worker = Resque::Worker.new(:test)
|
8
8
|
end
|
@@ -155,4 +155,41 @@ class LockTest < MiniTest::Unit::TestCase
|
|
155
155
|
diff = latest_lock - initial_lock
|
156
156
|
assert diff >= 1, 'diff between initial lock and refreshed lock should be at least 1 second'
|
157
157
|
end
|
158
|
+
|
159
|
+
def test_cannot_enqueue_two_loner_jobs
|
160
|
+
Resque.enqueue(LonelyJob)
|
161
|
+
Resque.enqueue(LonelyJob)
|
162
|
+
assert_equal 1, Resque.size(:test), '1 job should be enqueued'
|
163
|
+
|
164
|
+
Resque.enqueue(LonelyTimeoutJob)
|
165
|
+
Resque.enqueue(LonelyTimeoutJob)
|
166
|
+
assert_equal 2, Resque.size(:test), '2 jobs should be enqueued'
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_loner_job_should_not_be_enqued_if_already_running
|
170
|
+
Resque.enqueue(LonelyJob)
|
171
|
+
thread = Thread.new { @worker.process }
|
172
|
+
|
173
|
+
sleep 0.1 # The LonelyJob should be running (perfom is 0.2 seconds long)
|
174
|
+
Resque.enqueue(LonelyJob)
|
175
|
+
assert_equal 0, Resque.size(:test)
|
176
|
+
assert_equal 1, $enqueue_failed, 'One job callback should increment enqueue_failed'
|
177
|
+
|
178
|
+
thread.join
|
179
|
+
assert_equal 1, $success, 'One job should increment success'
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_loner_job_with_timeout_should_not_be_enqued_if_already_running
|
183
|
+
Resque.enqueue(LonelyTimeoutJob)
|
184
|
+
thread = Thread.new { @worker.process }
|
185
|
+
|
186
|
+
sleep 0.1 # Job should be running (perfom is 0.2 seconds long)
|
187
|
+
Resque.enqueue(LonelyTimeoutJob)
|
188
|
+
assert_equal 0, Resque.size(:test)
|
189
|
+
assert_equal 1, $enqueue_failed, 'One job callback should increment enqueue_failed'
|
190
|
+
|
191
|
+
thread.join
|
192
|
+
assert_equal 1, $success, 'One job should increment success'
|
193
|
+
end
|
194
|
+
|
158
195
|
end
|
data/test/redis-test.conf
CHANGED
@@ -6,10 +6,10 @@ daemonize yes
|
|
6
6
|
|
7
7
|
# When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
|
8
8
|
# You can specify a custom pid file location here.
|
9
|
-
pidfile ./test/redis-test.pid
|
9
|
+
#pidfile ./test/redis-test.pid
|
10
10
|
|
11
11
|
# Accept connections on the specified port, default is 6379
|
12
|
-
port
|
12
|
+
port 9737
|
13
13
|
|
14
14
|
# If you want you can bind a single interface, if the bind option is not
|
15
15
|
# specified all the interfaces will listen for connections.
|
@@ -30,16 +30,16 @@ timeout 300
|
|
30
30
|
# after 900 sec (15 min) if at least 1 key changed
|
31
31
|
# after 300 sec (5 min) if at least 10 keys changed
|
32
32
|
# after 60 sec if at least 10000 keys changed
|
33
|
-
save 900 1
|
34
|
-
save 300 10
|
35
|
-
save 60 10000
|
33
|
+
#save 900 1
|
34
|
+
#save 300 10
|
35
|
+
#save 60 10000
|
36
36
|
|
37
37
|
# The filename where to dump the DB
|
38
|
-
dbfilename dump.rdb
|
38
|
+
#dbfilename dump.rdb
|
39
39
|
|
40
40
|
# For default save/load DB in/from the working directory
|
41
41
|
# Note that you must specify a directory not a file name.
|
42
|
-
dir ./test/
|
42
|
+
#dir ./test/
|
43
43
|
|
44
44
|
# Set server verbosity to 'debug'
|
45
45
|
# it can be one of:
|
@@ -112,4 +112,4 @@ databases 16
|
|
112
112
|
# Glue small output buffers together in order to send small replies in a
|
113
113
|
# single TCP packet. Uses a bit more CPU but most of the times it is a win
|
114
114
|
# in terms of number of queries per second. Use 'yes' if unsure.
|
115
|
-
glueoutputbuf yes
|
115
|
+
# glueoutputbuf yes
|
data/test/test_helper.rb
CHANGED
@@ -5,36 +5,39 @@ $TESTING = true
|
|
5
5
|
require 'rubygems'
|
6
6
|
require 'minitest/unit'
|
7
7
|
require 'minitest/pride'
|
8
|
-
require 'simplecov'
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
# Run code coverage in MRI 1.9 only.
|
10
|
+
if RUBY_VERSION >= '1.9' && RUBY_ENGINE == 'ruby'
|
11
|
+
require 'simplecov'
|
12
|
+
SimpleCov.start do
|
13
|
+
add_filter '/test/'
|
14
|
+
end
|
15
|
+
end
|
13
16
|
|
14
17
|
require 'resque-lock-timeout'
|
15
18
|
require dir + '/test_jobs'
|
16
19
|
|
17
|
-
# make sure we can run redis
|
20
|
+
# make sure we can run redis-server
|
18
21
|
if !system('which redis-server')
|
19
|
-
puts '', "**
|
20
|
-
puts '** try running `sudo rake install`'
|
22
|
+
puts '', "** `redis-server` was not found in your PATH"
|
21
23
|
abort ''
|
22
24
|
end
|
23
25
|
|
24
|
-
#
|
25
|
-
|
26
|
+
# make sure we can shutdown the server using cli.
|
27
|
+
if !system('which redis-cli')
|
28
|
+
puts '', "** `redis-cli` was not found in your PATH"
|
29
|
+
abort ''
|
30
|
+
end
|
31
|
+
|
32
|
+
# This code is run `at_exit` to setup everything before running the tests.
|
33
|
+
# Redis server is started before this code block runs.
|
26
34
|
at_exit do
|
27
35
|
next if $!
|
28
36
|
|
29
37
|
exit_code = MiniTest::Unit.new.run(ARGV)
|
30
|
-
|
31
|
-
pid = `ps -e -o pid,command | grep [r]edis-test`.split(' ')[0]
|
32
|
-
puts 'Killing test redis server...'
|
33
|
-
`rm -f #{dir}/dump.rdb`
|
34
|
-
`kill -9 #{pid}`
|
35
|
-
exit(exit_code)
|
38
|
+
`redis-cli -p 9737 shutdown nosave`
|
36
39
|
end
|
37
40
|
|
38
|
-
puts
|
41
|
+
puts "Starting redis for testing at localhost:9737..."
|
39
42
|
`redis-server #{dir}/redis-test.conf`
|
40
|
-
Resque.redis = '127.0.0.1:
|
43
|
+
Resque.redis = '127.0.0.1:9737'
|
data/test/test_jobs.rb
CHANGED
@@ -112,4 +112,37 @@ class RefreshLockJob
|
|
112
112
|
extend Resque::Plugins::LockTimeout
|
113
113
|
@queue = :test
|
114
114
|
@lock_timeout = 60
|
115
|
-
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Job that prevents the job being enqueued if already enqueued/running.
|
118
|
+
class LonelyJob
|
119
|
+
extend Resque::Plugins::LockTimeout
|
120
|
+
@queue = :test
|
121
|
+
@loner = true
|
122
|
+
|
123
|
+
def self.perform
|
124
|
+
$success += 1
|
125
|
+
sleep 0.2
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.loner_enqueue_failed(*args)
|
129
|
+
$enqueue_failed += 1
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Exclusive job (only one queued/running) with a timeout.
|
134
|
+
class LonelyTimeoutJob
|
135
|
+
extend Resque::Plugins::LockTimeout
|
136
|
+
@queue = :test
|
137
|
+
@loner = true
|
138
|
+
@lock_timeout = 60
|
139
|
+
|
140
|
+
def self.perform
|
141
|
+
$success += 1
|
142
|
+
sleep 0.2
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.loner_enqueue_failed(*args)
|
146
|
+
$enqueue_failed += 1
|
147
|
+
end
|
148
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque-lock-timeout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,11 +11,11 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-
|
14
|
+
date: 2012-11-09 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: resque
|
18
|
-
requirement:
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ! '>='
|
@@ -23,10 +23,15 @@ dependencies:
|
|
23
23
|
version: 1.8.0
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
version_requirements:
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - ! '>='
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 1.8.0
|
27
32
|
- !ruby/object:Gem::Dependency
|
28
33
|
name: rake
|
29
|
-
requirement:
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
30
35
|
none: false
|
31
36
|
requirements:
|
32
37
|
- - ! '>='
|
@@ -34,10 +39,15 @@ dependencies:
|
|
34
39
|
version: '0'
|
35
40
|
type: :development
|
36
41
|
prerelease: false
|
37
|
-
version_requirements:
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
38
48
|
- !ruby/object:Gem::Dependency
|
39
49
|
name: minitest
|
40
|
-
requirement:
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
41
51
|
none: false
|
42
52
|
requirements:
|
43
53
|
- - ! '>='
|
@@ -45,10 +55,15 @@ dependencies:
|
|
45
55
|
version: '0'
|
46
56
|
type: :development
|
47
57
|
prerelease: false
|
48
|
-
version_requirements:
|
58
|
+
version_requirements: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
49
64
|
- !ruby/object:Gem::Dependency
|
50
65
|
name: json
|
51
|
-
requirement:
|
66
|
+
requirement: !ruby/object:Gem::Requirement
|
52
67
|
none: false
|
53
68
|
requirements:
|
54
69
|
- - ! '>='
|
@@ -56,10 +71,15 @@ dependencies:
|
|
56
71
|
version: '0'
|
57
72
|
type: :development
|
58
73
|
prerelease: false
|
59
|
-
version_requirements:
|
74
|
+
version_requirements: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
60
80
|
- !ruby/object:Gem::Dependency
|
61
81
|
name: yard
|
62
|
-
requirement:
|
82
|
+
requirement: !ruby/object:Gem::Requirement
|
63
83
|
none: false
|
64
84
|
requirements:
|
65
85
|
- - ! '>='
|
@@ -67,10 +87,15 @@ dependencies:
|
|
67
87
|
version: '0'
|
68
88
|
type: :development
|
69
89
|
prerelease: false
|
70
|
-
version_requirements:
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
71
96
|
- !ruby/object:Gem::Dependency
|
72
97
|
name: rdiscount
|
73
|
-
requirement:
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
74
99
|
none: false
|
75
100
|
requirements:
|
76
101
|
- - ! '>='
|
@@ -78,10 +103,15 @@ dependencies:
|
|
78
103
|
version: '0'
|
79
104
|
type: :development
|
80
105
|
prerelease: false
|
81
|
-
version_requirements:
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ! '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
82
112
|
- !ruby/object:Gem::Dependency
|
83
113
|
name: simplecov
|
84
|
-
requirement:
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
85
115
|
none: false
|
86
116
|
requirements:
|
87
117
|
- - ! '>='
|
@@ -89,9 +119,14 @@ dependencies:
|
|
89
119
|
version: 0.3.0
|
90
120
|
type: :development
|
91
121
|
prerelease: false
|
92
|
-
version_requirements:
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ! '>='
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: 0.3.0
|
93
128
|
description: ! " A Resque plugin. Adds locking, with optional timeout/deadlock handling
|
94
|
-
to\n resque jobs.\n\n Using a `lock_timeout` allows you to re-
|
129
|
+
to\n resque jobs.\n\n Using a `lock_timeout` allows you to re-acquire the lock
|
95
130
|
should your worker\n fail, crash, or is otherwise unable to relase the lock.\n
|
96
131
|
\ \n i.e. Your server unexpectedly looses power. Very handy for jobs that are\n
|
97
132
|
\ recurring or may be retried.\n"
|
@@ -130,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
165
|
version: '0'
|
131
166
|
requirements: []
|
132
167
|
rubyforge_project:
|
133
|
-
rubygems_version: 1.8.
|
168
|
+
rubygems_version: 1.8.24
|
134
169
|
signing_key:
|
135
170
|
specification_version: 3
|
136
171
|
summary: A Resque plugin adding locking, with optional timeout/deadlock handling to
|