resque-retry 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/HISTORY.md +7 -0
- data/README.md +26 -7
- data/examples/demo/Rakefile +1 -1
- data/lib/resque-retry.rb +1 -1
- data/lib/resque-retry/server.rb +1 -1
- data/lib/resque-retry/version.rb +1 -1
- data/lib/resque/plugins/retry.rb +43 -8
- data/resque-retry.gemspec +1 -1
- data/test/retry_test.rb +27 -19
- data/test/test_jobs.rb +32 -13
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66d34a270a535f97586c21a6c259d780c7a1ce9f
|
4
|
+
data.tar.gz: 9ab5f4591d2a99e262cc1ab2501d70e845f710aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03b4b70d9ef0e69d46d738fb3b6c1dd987e3e0e46cf3a2724300b50e1fbdcfc9f44d2af1b18b53999a21e74d48e335fe1a689e9885e14e784070ad5384f1fcac
|
7
|
+
data.tar.gz: 781a313ebd129ad8db24df9822b47bec750879aa2fa1abcc524df00228767c6a50eca03c780b19aee8e576304fcb294fe83f963af8fb75beacf4cb89b3f631fb
|
data/.travis.yml
CHANGED
data/HISTORY.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
## HEAD
|
2
2
|
|
3
|
+
## 1.3.0 (2014-07-25)
|
4
|
+
|
5
|
+
* Adjust gem dependency on `resque-scheduler` to ~> 3.0
|
6
|
+
* Deprecated: `args_for_retry` in favor of `retry_args` (will output deprecation warnings if your using the older method).
|
7
|
+
* Feature: Allow changing the args for a given exception using `retry_args_for_exception` (@jonp)
|
8
|
+
* Feature: Allow setting `@expire_retry_key_after` on the fly (@orenmazor)
|
9
|
+
|
3
10
|
## 1.2.1 (2014-06-09)
|
4
11
|
|
5
12
|
* Fixed Kernel.rand: "invalid argument - 0.0 (ArgumentError)" error with "ExponentialBackoff" (on "Rubinius") when `retry_delay_multiplicand_min` and `retry_delay_multiplicand_max` were the same value (@saizai)
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
resque-retry
|
2
2
|
============
|
3
3
|
|
4
|
-
A [Resque][rq] plugin. Requires Resque ~> 1.25 & [resque-scheduler][rqs] ~>
|
4
|
+
A [Resque][rq] plugin. Requires Resque ~> 1.25 & [resque-scheduler][rqs] ~> 3.0.
|
5
5
|
|
6
6
|
resque-retry provides retry, delay and exponential backoff support for
|
7
7
|
resque jobs.
|
@@ -28,7 +28,7 @@ If you're using [Bundler][bundler] to manage your dependencies, you should add `
|
|
28
28
|
Add this to your `Rakefile`:
|
29
29
|
```ruby
|
30
30
|
require 'resque/tasks'
|
31
|
-
require '
|
31
|
+
require 'resque/scheduler/tasks'
|
32
32
|
```
|
33
33
|
|
34
34
|
The delay between retry attempts is provided by [resque-scheduler][rqs].
|
@@ -120,8 +120,8 @@ run Resque::Server.new
|
|
120
120
|
Retry Options & Logic
|
121
121
|
---------------------
|
122
122
|
|
123
|
-
Please take a look at the yardoc/code
|
124
|
-
wish to override.
|
123
|
+
Please take a look at the [yardoc](http://rubydoc.info/gems/resque-retry)/code
|
124
|
+
for more details on methods you may wish to override.
|
125
125
|
|
126
126
|
Customisation is pretty easy, the below examples should give you
|
127
127
|
some ideas =), adapt for your own usage and feel free to pick and mix!
|
@@ -332,7 +332,7 @@ job should retry.
|
|
332
332
|
|
333
333
|
### Retry Arguments
|
334
334
|
|
335
|
-
You may override `
|
335
|
+
You may override `retry_args`, which is passed the current
|
336
336
|
job arguments, to modify the arguments for the next retry attempt.
|
337
337
|
```ruby
|
338
338
|
class DeliverViaSMSC
|
@@ -340,7 +340,7 @@ class DeliverViaSMSC
|
|
340
340
|
@queue = :mt_smsc_messages
|
341
341
|
|
342
342
|
# retry using the emergency SMSC.
|
343
|
-
def self.
|
343
|
+
def self.retry_args(smsc_id, mt_message)
|
344
344
|
[999, mt_message]
|
345
345
|
end
|
346
346
|
|
@@ -350,6 +350,25 @@ class DeliverViaSMSC
|
|
350
350
|
end
|
351
351
|
```
|
352
352
|
|
353
|
+
Alternatively, if you require finer control of the args based on the
|
354
|
+
exception thrown, you may override `retry_args_for_exception`, which is passed
|
355
|
+
the exception and the current job arguments, to modify the arguments for the
|
356
|
+
next retry attempt.
|
357
|
+
```ruby
|
358
|
+
class DeliverViaSMSC
|
359
|
+
extend Resque::Plugins::Retry
|
360
|
+
@queue = :mt_smsc_messages
|
361
|
+
|
362
|
+
# retry using the emergency SMSC.
|
363
|
+
def self.retry_args_for_exception(exception, smsc_id, mt_message)
|
364
|
+
[999, mt_message + exception.message]
|
365
|
+
end
|
366
|
+
|
367
|
+
self.perform(smsc_id, mt_message)
|
368
|
+
heavy_lifting
|
369
|
+
end
|
370
|
+
end
|
371
|
+
```
|
353
372
|
### Job Retry Identifier/Key
|
354
373
|
|
355
374
|
The retry attempt is incremented and stored in a Redis key. The key is
|
@@ -401,7 +420,7 @@ This saves you from having to run a "house cleaning" or "errand" job.
|
|
401
420
|
The expiary timeout is "pushed forward" or "touched" after each failure to
|
402
421
|
ensure its not expired too soon.
|
403
422
|
|
404
|
-
### Debug
|
423
|
+
### Debug Plugin Logging
|
405
424
|
|
406
425
|
The inner-workings of the plugin are output to the Resque [Logger](https://github.com/resque/resque/wiki/Logging)
|
407
426
|
when `Resque.logger.level` is set to `Logger::DEBUG`.
|
data/examples/demo/Rakefile
CHANGED
@@ -12,7 +12,7 @@ require 'resque/failure/redis'
|
|
12
12
|
|
13
13
|
# Require Rakefile related resque things.
|
14
14
|
require 'resque/tasks'
|
15
|
-
require '
|
15
|
+
require 'resque/scheduler/tasks'
|
16
16
|
|
17
17
|
# Enable resque-retry failure backend.
|
18
18
|
Resque::Failure::MultipleWithRetrySuppression.classes = [Resque::Failure::Redis]
|
data/lib/resque-retry.rb
CHANGED
data/lib/resque-retry/server.rb
CHANGED
data/lib/resque-retry/version.rb
CHANGED
data/lib/resque/plugins/retry.rb
CHANGED
@@ -154,8 +154,27 @@ module Resque
|
|
154
154
|
# @return [Array] new job arguments
|
155
155
|
#
|
156
156
|
# @api public
|
157
|
-
def
|
158
|
-
|
157
|
+
def retry_args(*args)
|
158
|
+
# Here for backwards compatibility. If an "args_for_retry" method exists
|
159
|
+
# invoke it, but warn that it is deprecated (and will be removed in a
|
160
|
+
# future revision)
|
161
|
+
if respond_to?(:args_for_retry)
|
162
|
+
warn "`Resque::Plugins::Retry#args_for_retry` is deprecated, please use `Resque::Plugins::Retry#retry_args` instead."
|
163
|
+
args_for_retry(*args)
|
164
|
+
else
|
165
|
+
args
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# @abstract
|
170
|
+
# Modify the arguments used to retry the job based on the exception.
|
171
|
+
# Use this to do something other than try the exact same job again.
|
172
|
+
#
|
173
|
+
# @return [Array] new job arguments
|
174
|
+
#
|
175
|
+
# @api public
|
176
|
+
def retry_args_for_exception(exception, *args)
|
177
|
+
retry_args(*args)
|
159
178
|
end
|
160
179
|
|
161
180
|
# Convenience method to test whether you may retry on a given
|
@@ -223,6 +242,14 @@ module Resque
|
|
223
242
|
end
|
224
243
|
end
|
225
244
|
|
245
|
+
# @abstract
|
246
|
+
# The number of seconds to set the TTL to on the resque-retry key in redis
|
247
|
+
#
|
248
|
+
# @return [Number] number of seconds
|
249
|
+
#
|
250
|
+
# @api public
|
251
|
+
attr_reader :expire_retry_key_after
|
252
|
+
|
226
253
|
# Test if the retry criteria is valid
|
227
254
|
#
|
228
255
|
# @param [Exception] exception
|
@@ -322,11 +349,13 @@ module Resque
|
|
322
349
|
# jobs that fail before ::perform will be both retried and sent to the failed queue.
|
323
350
|
Resque.redis.setnx(redis_retry_key(*args), -1)
|
324
351
|
|
352
|
+
retry_args = retry_args_for_exception(exception, *args)
|
353
|
+
|
325
354
|
if temp_retry_delay <= 0
|
326
355
|
# If the delay is 0, no point passing it through the scheduler
|
327
|
-
Resque.enqueue(retry_in_queue, *
|
356
|
+
Resque.enqueue(retry_in_queue, *retry_args)
|
328
357
|
else
|
329
|
-
Resque.enqueue_in(temp_retry_delay, retry_in_queue, *
|
358
|
+
Resque.enqueue_in(temp_retry_delay, retry_in_queue, *retry_args)
|
330
359
|
end
|
331
360
|
|
332
361
|
# remove retry key from redis if we handed retry off to another queue.
|
@@ -338,7 +367,8 @@ module Resque
|
|
338
367
|
|
339
368
|
# Resque before_perform hook
|
340
369
|
#
|
341
|
-
# Increments and
|
370
|
+
# Increments `@retry_attempt` count and updates the "retry_key" expiration
|
371
|
+
# time (if applicable)
|
342
372
|
#
|
343
373
|
# @api private
|
344
374
|
def before_perform_retry(*args)
|
@@ -347,10 +377,15 @@ module Resque
|
|
347
377
|
|
348
378
|
# store number of retry attempts.
|
349
379
|
retry_key = redis_retry_key(*args)
|
350
|
-
Resque.redis.setnx(retry_key, -1)
|
351
|
-
@retry_attempt = Resque.redis.incr(retry_key)
|
380
|
+
Resque.redis.setnx(retry_key, -1)
|
381
|
+
@retry_attempt = Resque.redis.incr(retry_key)
|
352
382
|
log_message "attempt: #{@retry_attempt} set in Redis", args
|
353
|
-
|
383
|
+
|
384
|
+
# set/update the "retry_key" expiration
|
385
|
+
if expire_retry_key_after
|
386
|
+
log_message "updating expiration for retry key: #{retry_key}", args
|
387
|
+
Resque.redis.expire(retry_key, retry_delay + expire_retry_key_after)
|
388
|
+
end
|
354
389
|
end
|
355
390
|
|
356
391
|
# Resque after_perform hook
|
data/resque-retry.gemspec
CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
|
|
30
30
|
s.require_paths = %w[lib]
|
31
31
|
|
32
32
|
s.add_dependency('resque', '~> 1.25')
|
33
|
-
s.add_dependency('resque-scheduler', '~>
|
33
|
+
s.add_dependency('resque-scheduler', '~> 3.0')
|
34
34
|
|
35
35
|
s.add_development_dependency('rake', '~> 10.1')
|
36
36
|
s.add_development_dependency('minitest', '~> 4.0')
|
data/test/retry_test.rb
CHANGED
@@ -55,12 +55,23 @@ class RetryTest < MiniTest::Unit::TestCase
|
|
55
55
|
assert_equal test_args, job['args']
|
56
56
|
end
|
57
57
|
|
58
|
-
def
|
59
|
-
Resque.enqueue(
|
58
|
+
def test_job_args_can_be_modified_by_overriding_args_for_retry
|
59
|
+
Resque.enqueue(DeprecatedRetryWithModifiedArgsJob)
|
60
|
+
DeprecatedRetryWithModifiedArgsJob.expects(:warn)
|
61
|
+
DeprecatedRetryWithModifiedArgsJob.expects(:args_for_retry)
|
60
62
|
perform_next_job(@worker)
|
63
|
+
end
|
61
64
|
|
62
|
-
|
63
|
-
|
65
|
+
def test_job_args_can_be_modified_by_overriding_retry_args
|
66
|
+
Resque.enqueue(RetryWithModifiedArgsJob)
|
67
|
+
RetryWithModifiedArgsJob.expects(:retry_args)
|
68
|
+
perform_next_job(@worker)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_job_args_can_be_modified_by_overriding_retry_args_for_exception
|
72
|
+
Resque.enqueue(RetryWithExceptionBasedArgsJob)
|
73
|
+
RetryWithExceptionBasedArgsJob.expects(:retry_args_for_exception)
|
74
|
+
perform_next_job(@worker)
|
64
75
|
end
|
65
76
|
|
66
77
|
def test_retry_never_give_up
|
@@ -286,22 +297,19 @@ class RetryTest < MiniTest::Unit::TestCase
|
|
286
297
|
perform_next_job(@worker)
|
287
298
|
end
|
288
299
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
end
|
299
|
-
Process.waitpid(child)
|
300
|
-
job.fail(Resque::DirtyExit.new)
|
301
|
-
end
|
300
|
+
def test_expire_key_setting_on_the_fly
|
301
|
+
retry_key = 'resque-retry:FailFiveTimesWithCustomExpiryJob'
|
302
|
+
|
303
|
+
Resque.redis.expects(:expire).
|
304
|
+
with(retry_key, 100).then.
|
305
|
+
with(retry_key, 101).then.
|
306
|
+
with(retry_key, 102).then.
|
307
|
+
with(retry_key, 103).then.
|
308
|
+
with(retry_key, 104)
|
302
309
|
|
303
|
-
|
310
|
+
Resque.enqueue(FailFiveTimesWithCustomExpiryJob)
|
311
|
+
5.times do
|
312
|
+
perform_next_job(@worker)
|
304
313
|
end
|
305
314
|
end
|
306
|
-
|
307
315
|
end
|
data/test/test_jobs.rb
CHANGED
@@ -41,7 +41,7 @@ class RetryDefaultsJob
|
|
41
41
|
@queue = :testing
|
42
42
|
|
43
43
|
def self.perform(*args)
|
44
|
-
raise
|
44
|
+
raise 'error'
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -102,11 +102,27 @@ class InheritTestWithMoreExtraJob < InheritTestWithExtraJob
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
|
-
class
|
105
|
+
class DeprecatedRetryWithModifiedArgsJob < RetryDefaultsJob
|
106
106
|
@queue = :testing
|
107
107
|
|
108
108
|
def self.args_for_retry(*args)
|
109
|
-
|
109
|
+
# NOTE: implementation is irrelevant we only care that it's invoked
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class RetryWithModifiedArgsJob < RetryDefaultsJob
|
114
|
+
@queue = :testing
|
115
|
+
|
116
|
+
def self.retry_args(*args)
|
117
|
+
# NOTE: implementation is irrelevant we only care that it's invoked
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class RetryWithExceptionBasedArgsJob < RetryDefaultsJob
|
122
|
+
@queue = :testing
|
123
|
+
|
124
|
+
def self.retry_args_for_exception(exception, *args)
|
125
|
+
# NOTE: implementation is irrelevant we only care that it's invoked
|
110
126
|
end
|
111
127
|
end
|
112
128
|
|
@@ -154,6 +170,19 @@ class FailFiveTimesWithExpiryJob < RetryDefaultsJob
|
|
154
170
|
end
|
155
171
|
end
|
156
172
|
|
173
|
+
class FailFiveTimesWithCustomExpiryJob < RetryDefaultsJob
|
174
|
+
@queue = :testing
|
175
|
+
@retry_limit = 6
|
176
|
+
|
177
|
+
def self.expire_retry_key_after
|
178
|
+
retry_attempt + 100
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.perform(*args)
|
182
|
+
raise if retry_attempt <= 4
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
157
186
|
class ExponentialBackoffJob < RetryDefaultsJob
|
158
187
|
extend Resque::Plugins::ExponentialBackoff
|
159
188
|
@queue = :testing
|
@@ -474,13 +503,3 @@ class FailsDuringConnectJob < RetryDefaultsJob
|
|
474
503
|
@retry_limit = 3
|
475
504
|
@retry_delay = 10
|
476
505
|
end
|
477
|
-
|
478
|
-
|
479
|
-
class RetryKilledJob
|
480
|
-
extend Resque::Plugins::Retry
|
481
|
-
@queue = :testing
|
482
|
-
|
483
|
-
def self.perform(*args)
|
484
|
-
Process.kill("KILL", Process.pid)
|
485
|
-
end
|
486
|
-
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque-retry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luke Antins
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-
|
13
|
+
date: 2014-07-25 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: resque
|
@@ -32,14 +32,14 @@ dependencies:
|
|
32
32
|
requirements:
|
33
33
|
- - "~>"
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: '
|
35
|
+
version: '3.0'
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
40
|
- - "~>"
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: '
|
42
|
+
version: '3.0'
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: rake
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|