resque-retry 1.5.0 → 1.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +7 -9
- data/HISTORY.md +16 -5
- data/README.md +46 -14
- data/lib/resque-retry/version.rb +1 -1
- data/lib/resque/plugins/retry.rb +45 -5
- data/test/ignore_exceptions_test.rb +38 -0
- data/test/resque_inline_test.rb +23 -0
- data/test/retry_test.rb +14 -11
- data/test/test_jobs.rb +26 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d298842f059d9cd8ee69821e345e60d8a792e68f8f7b9fb2041508cd57e540c3
|
4
|
+
data.tar.gz: 203fc1782c1bdcf08858075f110e34421d1e5b805869514a36b3122739f2487f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69bf34cb35ac34bf9975f4f2798dcb78dec39cfd0d373add776026aeaf5dbb594b70bfe2c0f8352701138a61095274413c3087dc14e251b96b117eea57c56207
|
7
|
+
data.tar.gz: b6602597785e8d13e1bb33883e852aece52d4b1e7ffc14f82843e42042c4219bfaa5cfeeec7a9a94176652b3bc59664535c218860127e7591ccd2f113ee80f83
|
data/.travis.yml
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
language: ruby
|
2
2
|
|
3
|
+
sudo: false
|
4
|
+
|
3
5
|
matrix:
|
4
6
|
allow_failures:
|
5
|
-
- rvm: jruby-
|
6
|
-
- rvm: rbx-2
|
7
|
+
- rvm: jruby-9.1.9.0
|
7
8
|
|
8
9
|
rvm:
|
9
|
-
-
|
10
|
-
- 2.
|
11
|
-
- 2.1
|
12
|
-
-
|
13
|
-
- 2.1.2
|
14
|
-
- jruby-19mode
|
15
|
-
- rbx-2
|
10
|
+
- 2.3.7
|
11
|
+
- 2.4.4
|
12
|
+
- 2.5.1
|
13
|
+
- jruby-9.1.9.0
|
data/HISTORY.md
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
|
1
|
+
# 1.5.2 (2018-07-16)
|
2
|
+
|
3
|
+
* Remove build support for `ruby < 2.3`, `jruby < 9.1` and `rbx`
|
4
|
+
* Improving custom retry criteria documentation (@iloveitaly)
|
5
|
+
|
6
|
+
# 1.5.1 (2018-01-07)
|
7
|
+
|
8
|
+
* Added build support for `ruby-2.2.x`, `ruby-2.3.x`, `ruby-2.4.x` and `ruby-2.5.x`
|
9
|
+
* Dropped build support for `ruby-1.9.3` and `ruby-2.0.0` (these versions are no unsupported)
|
10
|
+
* Fix some deprecation warnings in tests
|
11
|
+
* Feature: If no exact exception class is present in `@retry_exceptions` hash, try to find closest superclass (@fanfilmu)
|
12
|
+
* Feature: When running Resque inline, explicitly don't try to retry, don't touch Redis (@michaelglass)
|
2
13
|
|
3
14
|
# 1.5.0 (2015-10-24)
|
4
15
|
|
@@ -54,11 +65,11 @@
|
|
54
65
|
|
55
66
|
** !!! WARNING !!! INCLUDES NON-BACKWARDS COMPATIBLE CHANGES **
|
56
67
|
|
57
|
-
* Fixed issues related to
|
68
|
+
* Fixed issues related to infinite job retries and v1.20.0 of resque.
|
58
69
|
* Minimum gem dependency versions changed: resque >= 1.10.0, resque-scheduler >= 1.9.9
|
59
|
-
* Feature: Setting `@retry_job_delegate` allows you to
|
60
|
-
* Web interface will work without needing to `require` your job code. (n.b. less details
|
61
|
-
* IMPORTANT: `#identifier` method has been
|
70
|
+
* Feature: Setting `@retry_job_delegate` allows you to separate the original job from a the retry job. (@tanob/@jniesen)
|
71
|
+
* Web interface will work without needing to `require` your job code. (n.b. less details available via web).
|
72
|
+
* IMPORTANT: `#identifier` method has been namespaced to `#retry_identifier`.
|
62
73
|
* Bugfix: `Remove` button on retry web interface was not working.
|
63
74
|
* Feature: Allow `tagging` exceptions with a module instead of an exception class. (@tils - Tilmann Singer)
|
64
75
|
|
data/README.md
CHANGED
@@ -183,9 +183,10 @@ Here are a list of the options provided (click to jump):
|
|
183
183
|
* [Job Retry Identifier/Key](#retry_key)
|
184
184
|
* [Expire Retry Counters From Redis](#expire)
|
185
185
|
* [Try Again and Give Up Callbacks](#callbacks)
|
186
|
+
* [Ignored Exceptions](#ignored)
|
186
187
|
* [Debug Plugin Logging](#debug_log)
|
187
188
|
|
188
|
-
### <a name="retry_defaults"></a> Retry Defaults
|
189
|
+
### <a name="retry_defaults"></a> Retry Defaults
|
189
190
|
|
190
191
|
Retry the job **once** on failure, with zero delay.
|
191
192
|
```ruby
|
@@ -357,6 +358,8 @@ In the above example, Resque would retry any `DeliverSMS` jobs that throw any
|
|
357
358
|
type of error other than `NetworkError`. If the job throws a `NetworkError` it
|
358
359
|
will be marked as "failed" immediately.
|
359
360
|
|
361
|
+
You should use either `@fatal_exceptions` or `@retry_exceptions`. If you specify `@fatal_exceptions` the `@retry_exceptions` are ignored.
|
362
|
+
|
360
363
|
### <a name="custom_check"></a> Custom Retry Criteria Check Callbacks
|
361
364
|
|
362
365
|
You may define custom retry criteria callbacks:
|
@@ -368,11 +371,11 @@ class TurkWorker
|
|
368
371
|
@retry_exceptions = [NetworkError]
|
369
372
|
|
370
373
|
retry_criteria_check do |exception, *args|
|
371
|
-
if exception.message =~ /
|
372
|
-
|
373
|
-
else
|
374
|
-
true # its okay for a retry attempt to continue.
|
374
|
+
if exception.message =~ /SpecialErrorMessageToRetry/
|
375
|
+
return true
|
375
376
|
end
|
377
|
+
|
378
|
+
false
|
376
379
|
end
|
377
380
|
|
378
381
|
def self.perform(job_id)
|
@@ -385,9 +388,18 @@ Similar to the previous example, this job will retry if either a
|
|
385
388
|
`NetworkError` (or subclass) exception is thrown **or** any of the callbacks
|
386
389
|
return true.
|
387
390
|
|
391
|
+
You'll want to return false by default in the `retry_criteria_check` callback since
|
392
|
+
the result of this callback is OR'd with the result of your `retry_exceptions` or
|
393
|
+
`fatal_exceptions` configuration. In other words, if you returned true your
|
394
|
+
`retry_exceptions` configuration would never be used.
|
395
|
+
|
396
|
+
If you want to AND the result of `fatal_exceptions` or `retry_exceptions` with
|
397
|
+
custom retry criteria, you'll need to implement your own logic in a `retry_criteria_check`
|
398
|
+
to check for `fatal_exceptions` or `retry_exceptions`.
|
399
|
+
|
388
400
|
You can also register a retry criteria check with a Symbol if the method is
|
389
401
|
already defined on the job class:
|
390
|
-
```
|
402
|
+
```ruby
|
391
403
|
class AlwaysRetryJob
|
392
404
|
extend Resque::Plugins::Retry
|
393
405
|
|
@@ -397,8 +409,9 @@ class AlwaysRetryJob
|
|
397
409
|
true
|
398
410
|
end
|
399
411
|
end
|
412
|
+
```
|
400
413
|
|
401
|
-
Use `@retry_exceptions = []` to **only** use your custom retry criteria checks
|
414
|
+
Use `@retry_exceptions = []` and `@fatal_exceptions = []` to **only** use your custom retry criteria checks
|
402
415
|
to determine if the job should retry.
|
403
416
|
|
404
417
|
NB: Your callback must be able to accept the exception and job arguments as
|
@@ -419,7 +432,7 @@ class DeliverViaSMSC
|
|
419
432
|
[999, mt_message]
|
420
433
|
end
|
421
434
|
|
422
|
-
self.perform(smsc_id, mt_message)
|
435
|
+
def self.perform(smsc_id, mt_message)
|
423
436
|
heavy_lifting
|
424
437
|
end
|
425
438
|
end
|
@@ -439,7 +452,7 @@ class DeliverViaSMSC
|
|
439
452
|
[999, mt_message + exception.message]
|
440
453
|
end
|
441
454
|
|
442
|
-
self.perform(smsc_id, mt_message)
|
455
|
+
def self.perform(smsc_id, mt_message)
|
443
456
|
heavy_lifting
|
444
457
|
end
|
445
458
|
end
|
@@ -466,7 +479,7 @@ class DeliverSMS
|
|
466
479
|
"#{mobile_number}:#{mt_id}"
|
467
480
|
end
|
468
481
|
|
469
|
-
self.perform(mt_id, mobile_number, message)
|
482
|
+
def self.perform(mt_id, mobile_number, message)
|
470
483
|
heavy_lifting
|
471
484
|
end
|
472
485
|
end
|
@@ -482,7 +495,7 @@ class DeliverSMS
|
|
482
495
|
@queue = :mt_messages
|
483
496
|
@expire_retry_key_after = 3600 # expire key after `retry_delay` plus 1 hour
|
484
497
|
|
485
|
-
self.perform(mt_id, mobile_number, message)
|
498
|
+
def self.perform(mt_id, mobile_number, message)
|
486
499
|
heavy_lifting
|
487
500
|
end
|
488
501
|
end
|
@@ -512,7 +525,7 @@ _not_ retrying, you can add a `give_up_callback`:
|
|
512
525
|
```ruby
|
513
526
|
class LoggedJob
|
514
527
|
extend Resque::Plugins::Retry
|
515
|
-
|
528
|
+
|
516
529
|
give_up_callback do |exception, *args|
|
517
530
|
logger.error("Received #{exception}, job #{self.name} failed with #{args}")
|
518
531
|
end
|
@@ -524,10 +537,10 @@ the job class:
|
|
524
537
|
```ruby
|
525
538
|
class LoggedJob
|
526
539
|
extend Resque::Plugins::Retry
|
527
|
-
|
540
|
+
|
528
541
|
give_up_callback :log_give_up
|
529
542
|
|
530
|
-
def self.log_give_up(
|
543
|
+
def self.log_give_up(exception, *args)
|
531
544
|
logger.error("Received #{exception}, job #{self.name} failed with #{args}")
|
532
545
|
end
|
533
546
|
end
|
@@ -557,6 +570,25 @@ Warning: Make sure your callbacks do not throw any exceptions. If they do,
|
|
557
570
|
subsequent callbacks will not be triggered, and the job will not be retried
|
558
571
|
(if it was trying again). The retry counter also will not be reset.
|
559
572
|
|
573
|
+
### <a name="ignored"></a> Ignored Exceptions
|
574
|
+
If there is an exception for which you want to retry, but you don't want it to
|
575
|
+
increment your retry counter, you can add it to `@ignore_exceptions`.
|
576
|
+
|
577
|
+
One use case: Restarting your workers triggers a `Resque::TermException`. You
|
578
|
+
may want your workers to retry the job that they were working on, but without
|
579
|
+
incrementing the retry counter.
|
580
|
+
|
581
|
+
```ruby
|
582
|
+
class RestartResilientJob
|
583
|
+
extend Resque::Plugins::Retry
|
584
|
+
|
585
|
+
@retry_exceptions = [Resque::TermException]
|
586
|
+
@ignore_exceptions = [Resque::TermException]
|
587
|
+
end
|
588
|
+
```
|
589
|
+
|
590
|
+
Reminder: `@ignore_exceptions` should be a subset of `@retry_exceptions`.
|
591
|
+
|
560
592
|
### <a name="debug_log"></a> Debug Plugin Logging
|
561
593
|
|
562
594
|
The inner-workings of the plugin are output to the Resque [Logger](https://github.com/resque/resque/wiki/Logging)
|
data/lib/resque-retry/version.rb
CHANGED
data/lib/resque/plugins/retry.rb
CHANGED
@@ -43,13 +43,34 @@ module Resque
|
|
43
43
|
# @api public
|
44
44
|
class AmbiguousRetryStrategyException < StandardError; end
|
45
45
|
|
46
|
+
# Raised if there is a problem with the configuration of resque-retry.
|
47
|
+
#
|
48
|
+
# @api public
|
49
|
+
class RetryConfigurationException < StandardError; end
|
50
|
+
|
46
51
|
# Fail fast, when extended, if the "receiver" is misconfigured
|
47
52
|
#
|
48
53
|
# @api private
|
49
54
|
def self.extended(receiver)
|
50
|
-
|
55
|
+
retry_exceptions = receiver.instance_variable_get('@retry_exceptions')
|
56
|
+
fatal_exceptions = receiver.instance_variable_get('@fatal_exceptions')
|
57
|
+
ignore_exceptions = receiver.instance_variable_get('@ignore_exceptions')
|
58
|
+
|
59
|
+
if fatal_exceptions && retry_exceptions
|
51
60
|
raise AmbiguousRetryStrategyException.new(%{You can't define both "@fatal_exceptions" and "@retry_exceptions"})
|
52
61
|
end
|
62
|
+
|
63
|
+
# Check that ignore_exceptions is a subset of retry_exceptions
|
64
|
+
if retry_exceptions.is_a?(Hash)
|
65
|
+
exceptions = retry_exceptions.keys
|
66
|
+
else
|
67
|
+
exceptions = Array(retry_exceptions)
|
68
|
+
end
|
69
|
+
|
70
|
+
excess_exceptions = Array(ignore_exceptions) - exceptions
|
71
|
+
unless excess_exceptions.empty?
|
72
|
+
raise RetryConfigurationException, "The following exceptions are defined in @ignore_exceptions but not in @retry_exceptions: #{excess_exceptions.join(', ')}."
|
73
|
+
end
|
53
74
|
end
|
54
75
|
|
55
76
|
# Copy retry criteria checks, try again callbacks, and give up callbacks
|
@@ -115,13 +136,18 @@ module Resque
|
|
115
136
|
|
116
137
|
# @abstract
|
117
138
|
# Number of seconds to delay until the job is retried
|
139
|
+
# If @retry_exceptions is a Hash and there is no delay defined for exception_class,
|
140
|
+
# looks for closest superclass and assigns it's delay to @retry_exceptions[exception_class]
|
118
141
|
#
|
119
142
|
# @return [Number] number of seconds to delay
|
120
143
|
#
|
121
144
|
# @api public
|
122
145
|
def retry_delay(exception_class = nil)
|
123
146
|
if @retry_exceptions.is_a?(Hash)
|
124
|
-
delay = @retry_exceptions[exception_class]
|
147
|
+
delay = @retry_exceptions[exception_class] ||= begin
|
148
|
+
relevant_definitions = @retry_exceptions.select { |ex| exception_class <= ex }
|
149
|
+
relevant_definitions.any? ? relevant_definitions.sort.first[1] : 0
|
150
|
+
end
|
125
151
|
# allow an array of delays.
|
126
152
|
delay.is_a?(Array) ? delay[retry_attempt] || delay.last : delay
|
127
153
|
else
|
@@ -131,7 +157,7 @@ module Resque
|
|
131
157
|
|
132
158
|
# @abstract
|
133
159
|
# Number of seconds to sleep after job is requeued
|
134
|
-
#
|
160
|
+
#
|
135
161
|
# @return [Number] number of seconds to sleep
|
136
162
|
#
|
137
163
|
# @api public
|
@@ -264,7 +290,7 @@ module Resque
|
|
264
290
|
# if the retry limit was reached, dont bother checking anything else.
|
265
291
|
if retry_limit_reached?
|
266
292
|
log_message 'retry limit reached', args, exception
|
267
|
-
return false
|
293
|
+
return false
|
268
294
|
end
|
269
295
|
|
270
296
|
# We always want to retry if the exception matches.
|
@@ -369,7 +395,7 @@ module Resque
|
|
369
395
|
|
370
396
|
# remember that this job is now being retried. before_perform_retry will increment
|
371
397
|
# this so it represents the retry count, and MultipleWithRetrySuppression uses
|
372
|
-
# the existence of this to determine if the job should be sent to the
|
398
|
+
# the existence of this to determine if the job should be sent to the
|
373
399
|
# parent failure backend (e.g. failed queue) or not. Removing this means
|
374
400
|
# jobs that fail before ::perform will be both retried and sent to the failed queue.
|
375
401
|
Resque.redis.setnx(redis_retry_key(*args), -1)
|
@@ -406,6 +432,7 @@ module Resque
|
|
406
432
|
#
|
407
433
|
# @api private
|
408
434
|
def before_perform_retry(*args)
|
435
|
+
return if Resque.inline?
|
409
436
|
log_message 'before_perform_retry', args
|
410
437
|
@on_failure_retry_hook_already_called = false
|
411
438
|
|
@@ -428,6 +455,7 @@ module Resque
|
|
428
455
|
#
|
429
456
|
# @api private
|
430
457
|
def after_perform_retry(*args)
|
458
|
+
return if Resque.inline?
|
431
459
|
log_message 'after_perform_retry, clearing retry key', args
|
432
460
|
clean_retry_key(*args)
|
433
461
|
end
|
@@ -443,6 +471,7 @@ module Resque
|
|
443
471
|
#
|
444
472
|
# @api private
|
445
473
|
def on_failure_retry(exception, *args)
|
474
|
+
return if Resque.inline?
|
446
475
|
log_message 'on_failure_retry', args, exception
|
447
476
|
if exception.is_a?(Resque::DirtyExit)
|
448
477
|
# This hook is called from a worker processes, not the job process
|
@@ -453,6 +482,13 @@ module Resque
|
|
453
482
|
return
|
454
483
|
end
|
455
484
|
|
485
|
+
# If we are "ignoring" the exception, then we decrement the retry
|
486
|
+
# counter, so that the current attempt didn't count toward the retry
|
487
|
+
# counter.
|
488
|
+
if ignore_exceptions.include?(exception.class)
|
489
|
+
@retry_attempt = Resque.redis.decr(redis_retry_key(*args))
|
490
|
+
end
|
491
|
+
|
456
492
|
if retry_criteria_valid?(exception, *args)
|
457
493
|
try_again(exception, *args)
|
458
494
|
else
|
@@ -584,6 +620,10 @@ module Resque
|
|
584
620
|
end
|
585
621
|
end
|
586
622
|
|
623
|
+
def ignore_exceptions
|
624
|
+
@ignore_exceptions ||= []
|
625
|
+
end
|
626
|
+
|
587
627
|
# Helper to call functions that may be passed as Symbols or Procs. If
|
588
628
|
# a symbol, it is assumed to refer to a method that is already defined
|
589
629
|
# on this class.
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class IgnoreExceptionsTest < Minitest::Test
|
4
|
+
def setup
|
5
|
+
Resque.redis.flushall
|
6
|
+
@worker = Resque::Worker.new(:testing)
|
7
|
+
@worker.register_worker
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_ignore_exceptions
|
11
|
+
Resque.enqueue(IgnoreExceptionsJob)
|
12
|
+
retry_key = IgnoreExceptionsJob.redis_retry_key
|
13
|
+
|
14
|
+
IgnoreExceptionsJob.stubs(:perform).raises(AnotherCustomException)
|
15
|
+
perform_next_job(@worker)
|
16
|
+
assert_equal '0', Resque.redis.get(retry_key), 'retry counter'
|
17
|
+
|
18
|
+
IgnoreExceptionsJob.stubs(:perform).raises(AnotherCustomException)
|
19
|
+
perform_next_job(@worker)
|
20
|
+
assert_equal '1', Resque.redis.get(retry_key), 'retry counter'
|
21
|
+
|
22
|
+
IgnoreExceptionsJob.stubs(:perform).raises(CustomException)
|
23
|
+
perform_next_job(@worker)
|
24
|
+
assert_equal '1', Resque.redis.get(retry_key), 'retry counter'
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_ignore_exception_configuration_1
|
28
|
+
assert_raises Resque::Plugins::Retry::RetryConfigurationException do
|
29
|
+
IgnoreExceptionsImproperlyConfiguredJob1.extend(Resque::Plugins::Retry)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_ignore_exception_configuration_2
|
34
|
+
assert_raises Resque::Plugins::Retry::RetryConfigurationException do
|
35
|
+
IgnoreExceptionsImproperlyConfiguredJob2.extend(Resque::Plugins::Retry)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ResqueInlineTest < Minitest::Test
|
4
|
+
def setup
|
5
|
+
Resque.inline = true
|
6
|
+
Resque.expects(:redis).never
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
Resque.inline = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_runs_inline
|
14
|
+
GoodJob.expects :perform
|
15
|
+
Resque.enqueue(GoodJob)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_fails_inline
|
19
|
+
assert_raises CustomException do
|
20
|
+
Resque.enqueue(RetryCustomExceptionsJob, 'CustomException')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/test/retry_test.rb
CHANGED
@@ -18,8 +18,8 @@ class RetryTest < Minitest::Test
|
|
18
18
|
def test_default_settings
|
19
19
|
assert_equal 1, RetryDefaultSettingsJob.retry_limit, 'default retry limit'
|
20
20
|
assert_equal 0, RetryDefaultSettingsJob.retry_attempt, 'default number of retry attempts'
|
21
|
-
|
22
|
-
|
21
|
+
assert_nil RetryDefaultSettingsJob.fatal_exceptions, 'default fatal exceptions; nil = none'
|
22
|
+
assert_nil RetryDefaultSettingsJob.retry_exceptions, 'default retry exceptions; nil = any'
|
23
23
|
assert_equal 0, RetryDefaultSettingsJob.retry_delay, 'default seconds until retry'
|
24
24
|
end
|
25
25
|
|
@@ -223,7 +223,7 @@ class RetryTest < Minitest::Test
|
|
223
223
|
|
224
224
|
assert job_from_retry_queue = Resque.pop(:testing_retry)
|
225
225
|
assert_equal ['arg1'], job_from_retry_queue['args']
|
226
|
-
|
226
|
+
assert_nil Resque.redis.get(JobWithRetryQueue.redis_retry_key('arg1'))
|
227
227
|
end
|
228
228
|
|
229
229
|
def test_clean_retry_key_should_splat_args
|
@@ -244,14 +244,14 @@ class RetryTest < Minitest::Test
|
|
244
244
|
def test_delete_redis_key_when_job_is_successful
|
245
245
|
Resque.enqueue(GoodJob, 'arg1')
|
246
246
|
|
247
|
-
|
247
|
+
assert_nil Resque.redis.get(GoodJob.redis_retry_key('arg1'))
|
248
248
|
perform_next_job(@worker)
|
249
|
-
|
249
|
+
assert_nil Resque.redis.get(GoodJob.redis_retry_key('arg1'))
|
250
250
|
end
|
251
251
|
|
252
252
|
def test_delete_redis_key_after_final_failed_retry
|
253
253
|
Resque.enqueue(FailFiveTimesJob, 'yarrrr')
|
254
|
-
|
254
|
+
assert_nil Resque.redis.get(FailFiveTimesJob.redis_retry_key('yarrrr'))
|
255
255
|
|
256
256
|
perform_next_job(@worker)
|
257
257
|
assert_equal '0', Resque.redis.get(FailFiveTimesJob.redis_retry_key('yarrrr'))
|
@@ -262,7 +262,7 @@ class RetryTest < Minitest::Test
|
|
262
262
|
5.times do
|
263
263
|
perform_next_job(@worker)
|
264
264
|
end
|
265
|
-
|
265
|
+
assert_nil Resque.redis.get(FailFiveTimesJob.redis_retry_key('yarrrr'))
|
266
266
|
|
267
267
|
assert_equal 5, Resque.info[:failed], 'failed jobs'
|
268
268
|
assert_equal 6, Resque.info[:processed], 'processed job'
|
@@ -286,9 +286,12 @@ class RetryTest < Minitest::Test
|
|
286
286
|
|
287
287
|
def test_retry_delay
|
288
288
|
assert_equal 3, NormalRetryCountJob.retry_delay
|
289
|
-
assert_equal 7, PerExceptionClassRetryCountJob.retry_delay(
|
290
|
-
assert_equal
|
291
|
-
assert_equal
|
289
|
+
assert_equal 7, PerExceptionClassRetryCountJob.retry_delay(StandardError)
|
290
|
+
assert_equal 7, PerExceptionClassRetryCountJob.retry_delay(CustomException)
|
291
|
+
assert_equal 11, PerExceptionClassRetryCountJob.retry_delay(AnotherCustomException)
|
292
|
+
assert_equal 13, PerExceptionClassRetryCountJob.retry_delay(HierarchyCustomException)
|
293
|
+
|
294
|
+
assert_equal 7, PerExceptionClassRetryCountJob.instance_variable_get("@retry_exceptions")[CustomException]
|
292
295
|
end
|
293
296
|
|
294
297
|
def test_expire_key_set
|
@@ -327,7 +330,7 @@ class RetryTest < Minitest::Test
|
|
327
330
|
job.fail(Resque::DirtyExit.new)
|
328
331
|
end
|
329
332
|
|
330
|
-
|
333
|
+
assert_nil @worker.reserve
|
331
334
|
end
|
332
335
|
end
|
333
336
|
end
|
data/test/test_jobs.rb
CHANGED
@@ -496,7 +496,7 @@ class PerExceptionClassRetryCountJob
|
|
496
496
|
|
497
497
|
@queue = :testing
|
498
498
|
@retry_limit = 3
|
499
|
-
@retry_exceptions = {
|
499
|
+
@retry_exceptions = { StandardError => 7, AnotherCustomException => 11, HierarchyCustomException => 13 }
|
500
500
|
|
501
501
|
def self.perform
|
502
502
|
raise RuntimeError, 'I always fail with a RuntimeError'
|
@@ -579,3 +579,28 @@ class RetryCallbacksJob
|
|
579
579
|
|
580
580
|
give_up_callback :on_give_up_c
|
581
581
|
end
|
582
|
+
|
583
|
+
class IgnoreExceptionsJob
|
584
|
+
extend Resque::Plugins::Retry
|
585
|
+
@queue = :testing
|
586
|
+
@ignore_exceptions = [CustomException]
|
587
|
+
@retry_exceptions = [CustomException, AnotherCustomException]
|
588
|
+
@retry_limit = 3
|
589
|
+
|
590
|
+
def self.perform
|
591
|
+
"Hello, World!"
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
class IgnoreExceptionsImproperlyConfiguredJob1
|
596
|
+
# Manually extend Resque::Plugins::Retry in the test code to catch the
|
597
|
+
# exception.
|
598
|
+
@ignore_exceptions = [CustomException]
|
599
|
+
end
|
600
|
+
|
601
|
+
class IgnoreExceptionsImproperlyConfiguredJob2
|
602
|
+
# Manually extend Resque::Plugins::Retry in the test code to catch the
|
603
|
+
# exception.
|
604
|
+
@ignore_exceptions = [CustomException]
|
605
|
+
@retry_exceptions = { AnotherCustomException => 0 }
|
606
|
+
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.5.
|
4
|
+
version: 1.5.2
|
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:
|
13
|
+
date: 2018-07-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: resque
|
@@ -181,8 +181,10 @@ files:
|
|
181
181
|
- lib/resque/plugins/retry/logging.rb
|
182
182
|
- resque-retry.gemspec
|
183
183
|
- test/exponential_backoff_test.rb
|
184
|
+
- test/ignore_exceptions_test.rb
|
184
185
|
- test/multiple_failure_test.rb
|
185
186
|
- test/redis-test.conf
|
187
|
+
- test/resque_inline_test.rb
|
186
188
|
- test/resque_test.rb
|
187
189
|
- test/retry_callbacks_test.rb
|
188
190
|
- test/retry_criteria_test.rb
|
@@ -214,10 +216,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
216
|
version: '0'
|
215
217
|
requirements: []
|
216
218
|
rubyforge_project:
|
217
|
-
rubygems_version: 2.
|
219
|
+
rubygems_version: 2.7.6
|
218
220
|
signing_key:
|
219
221
|
specification_version: 4
|
220
222
|
summary: A resque plugin; provides retry, delay and exponential backoff support for
|
221
223
|
resque jobs.
|
222
224
|
test_files: []
|
223
|
-
has_rdoc: false
|