resque-retry 1.5.0 → 1.7.6

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.
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class RetryTest < Minitest::Test
3
+ class RetryExceptionDelayTest < Minitest::Test
4
4
  def setup
5
5
  Resque.redis.flushall
6
6
  @worker = Resque::Worker.new(:testing)
@@ -43,4 +43,12 @@ class RetryTest < Minitest::Test
43
43
  assert_in_delta (start_time + 10), delayed[1], 1.00, '2nd retry delay timestamp'
44
44
  assert_in_delta (start_time + 15), delayed[2], 1.00, '3rd retry delay timestamp'
45
45
  end
46
+
47
+ def test_retry_delay_per_exception_multiple_delay_no_retry_limit_specified
48
+ # For this job-type there are 3 `Exception` types defined: `Exception`,
49
+ # `StandardError` and `Timeout::Error` -- their array-lengths are are 1, 3
50
+ # and 5 (respectively). We expect the `retry_limit` to default to the
51
+ # maximum length of the `Array` of delays or 1 (in this case: 5)
52
+ assert_equal 5, PerExceptionClassRetryCountArrayNoRetryLimitSpecifiedJob.retry_limit
53
+ end
46
54
  end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ class RetryQueueTest < 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_retry_delayed_failed_jobs_in_separate_queue
11
+ Resque.enqueue(DelayedJobWithRetryQueue, 'arg1')
12
+ Resque.expects(:enqueue_in_with_queue).with(:testing_retry_delegate, 1, JobRetryQueue, 'arg1')
13
+
14
+ perform_next_job(@worker)
15
+ end
16
+
17
+ def test_retry_delayed_failed_jobs_in_dynamic_queue
18
+ queue_name = "dynamic_queue_#{Time.now.to_i}"
19
+
20
+ Resque.enqueue(JobWithDynamicRetryQueue, queue_name)
21
+ Resque.expects(:enqueue_in_with_queue).with(queue_name, 1, JobWithDynamicRetryQueue, queue_name)
22
+
23
+ perform_next_job(@worker)
24
+ end
25
+ 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
- assert_equal nil, RetryDefaultSettingsJob.fatal_exceptions, 'default fatal exceptions; nil = none'
22
- assert_equal nil, RetryDefaultSettingsJob.retry_exceptions, 'default retry exceptions; nil = any'
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
 
@@ -55,13 +55,6 @@ class RetryTest < Minitest::Test
55
55
  assert_equal test_args, job['args']
56
56
  end
57
57
 
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)
62
- perform_next_job(@worker)
63
- end
64
-
65
58
  def test_job_args_can_be_modified_by_overriding_retry_args
66
59
  Resque.enqueue(RetryWithModifiedArgsJob)
67
60
  RetryWithModifiedArgsJob.expects(:retry_args)
@@ -221,9 +214,9 @@ class RetryTest < Minitest::Test
221
214
 
222
215
  perform_next_job(@worker)
223
216
 
224
- assert job_from_retry_queue = Resque.pop(:testing_retry)
217
+ assert job_from_retry_queue = Resque.pop(:testing_retry_delegate)
225
218
  assert_equal ['arg1'], job_from_retry_queue['args']
226
- assert_equal nil, Resque.redis.get(JobWithRetryQueue.redis_retry_key('arg1'))
219
+ assert_nil Resque.redis.get(JobWithRetryQueue.redis_retry_key('arg1'))
227
220
  end
228
221
 
229
222
  def test_clean_retry_key_should_splat_args
@@ -234,24 +227,17 @@ class RetryTest < Minitest::Test
234
227
  perform_next_job(@worker)
235
228
  end
236
229
 
237
- def test_retry_delayed_failed_jobs_in_separate_queue
238
- Resque.enqueue(DelayedJobWithRetryQueue, 'arg1')
239
- Resque.expects(:enqueue_in).with(1, JobRetryQueue, 'arg1')
240
-
241
- perform_next_job(@worker)
242
- end
243
-
244
230
  def test_delete_redis_key_when_job_is_successful
245
231
  Resque.enqueue(GoodJob, 'arg1')
246
232
 
247
- assert_equal nil, Resque.redis.get(GoodJob.redis_retry_key('arg1'))
233
+ assert_nil Resque.redis.get(GoodJob.redis_retry_key('arg1'))
248
234
  perform_next_job(@worker)
249
- assert_equal nil, Resque.redis.get(GoodJob.redis_retry_key('arg1'))
235
+ assert_nil Resque.redis.get(GoodJob.redis_retry_key('arg1'))
250
236
  end
251
237
 
252
238
  def test_delete_redis_key_after_final_failed_retry
253
239
  Resque.enqueue(FailFiveTimesJob, 'yarrrr')
254
- assert_equal nil, Resque.redis.get(FailFiveTimesJob.redis_retry_key('yarrrr'))
240
+ assert_nil Resque.redis.get(FailFiveTimesJob.redis_retry_key('yarrrr'))
255
241
 
256
242
  perform_next_job(@worker)
257
243
  assert_equal '0', Resque.redis.get(FailFiveTimesJob.redis_retry_key('yarrrr'))
@@ -262,7 +248,7 @@ class RetryTest < Minitest::Test
262
248
  5.times do
263
249
  perform_next_job(@worker)
264
250
  end
265
- assert_equal nil, Resque.redis.get(FailFiveTimesJob.redis_retry_key('yarrrr'))
251
+ assert_nil Resque.redis.get(FailFiveTimesJob.redis_retry_key('yarrrr'))
266
252
 
267
253
  assert_equal 5, Resque.info[:failed], 'failed jobs'
268
254
  assert_equal 6, Resque.info[:processed], 'processed job'
@@ -285,10 +271,14 @@ class RetryTest < Minitest::Test
285
271
  end
286
272
 
287
273
  def test_retry_delay
274
+ assert_equal 0, NoRetryDelayJob.retry_delay
288
275
  assert_equal 3, NormalRetryCountJob.retry_delay
289
- assert_equal 7, PerExceptionClassRetryCountJob.retry_delay(RuntimeError)
290
- assert_equal 11, PerExceptionClassRetryCountJob.retry_delay(Exception)
291
- assert_equal 13, PerExceptionClassRetryCountJob.retry_delay(Timeout::Error)
276
+ assert_equal 7, PerExceptionClassRetryCountJob.retry_delay(StandardError)
277
+ assert_equal 7, PerExceptionClassRetryCountJob.retry_delay(CustomException)
278
+ assert_equal 11, PerExceptionClassRetryCountJob.retry_delay(AnotherCustomException)
279
+ assert_equal 13, PerExceptionClassRetryCountJob.retry_delay(HierarchyCustomException)
280
+
281
+ assert_equal 7, PerExceptionClassRetryCountJob.instance_variable_get("@retry_exceptions")[CustomException]
292
282
  end
293
283
 
294
284
  def test_expire_key_set
@@ -297,6 +287,12 @@ class RetryTest < Minitest::Test
297
287
  perform_next_job(@worker)
298
288
  end
299
289
 
290
+ def test_expire_key_set_with_retry_exceptions
291
+ Resque.redis.expects(:expire).once.with(ExpiringJobWithRetryExceptions.redis_retry_key(StandardError), 17)
292
+ Resque.enqueue(ExpiringJobWithRetryExceptions, StandardError)
293
+ perform_next_job(@worker)
294
+ end
295
+
300
296
  def test_expire_key_setting_on_the_fly
301
297
  retry_key = 'resque-retry:FailFiveTimesWithCustomExpiryJob'
302
298
 
@@ -327,7 +323,7 @@ class RetryTest < Minitest::Test
327
323
  job.fail(Resque::DirtyExit.new)
328
324
  end
329
325
 
330
- assert_equal nil, @worker.reserve
326
+ assert_nil @worker.reserve
331
327
  end
332
328
  end
333
329
  end
data/test/test_helper.rb CHANGED
@@ -1,13 +1,8 @@
1
1
  dir = File.dirname(File.expand_path(__FILE__))
2
2
  $LOAD_PATH.unshift dir + '/../lib'
3
- $TESTING = true
4
3
 
5
- require 'rubygems'
6
- require 'timeout'
7
- require 'minitest/autorun'
8
- require 'minitest/pride'
9
- require 'rack/test'
10
- require 'mocha/setup'
4
+ $TESTING = true
5
+ $VERBOSE = ENV['VERBOSE'] != 'true' ? nil : true
11
6
 
12
7
  # Run code coverage in MRI 1.9 only.
13
8
  if RUBY_VERSION >= '1.9' && RUBY_ENGINE == 'ruby'
@@ -17,28 +12,39 @@ if RUBY_VERSION >= '1.9' && RUBY_ENGINE == 'ruby'
17
12
  end
18
13
  end
19
14
 
15
+ require 'rubygems'
16
+ require 'timeout'
17
+ require 'minitest/autorun'
18
+ require 'minitest/pride'
19
+ require 'rack/test'
20
+ require 'mocha/setup'
21
+
20
22
  require 'resque-retry'
21
23
  require dir + '/test_jobs'
22
24
 
23
- # make sure we can run redis-server
24
- if !system('which redis-server')
25
- puts '', "** `redis-server` was not found in your PATH"
26
- abort ''
27
- end
25
+ if ENV['CI'] != 'true'
26
+ # make sure we can run redis-server
27
+ if !system('which redis-server')
28
+ puts '', "** `redis-server` was not found in your PATH"
29
+ abort ''
30
+ end
28
31
 
29
- # make sure we can shutdown the server using cli.
30
- if !system('which redis-cli')
31
- puts '', "** `redis-cli` was not found in your PATH"
32
- abort ''
33
- end
32
+ # make sure we can shutdown the server using cli.
33
+ if !system('which redis-cli')
34
+ puts '', "** `redis-cli` was not found in your PATH"
35
+ abort ''
36
+ end
34
37
 
35
- # This code is run after all the tests have finished running to ensure that the
36
- # Redis server is shutdowa
37
- Minitest.after_run { `redis-cli -p 9736 shutdown nosave` }
38
+ # This code is run after all the tests have finished running to ensure that the
39
+ # Redis server is shutdowa
40
+ Minitest.after_run { `redis-cli -p 9736 shutdown nosave` }
38
41
 
39
- puts "Starting redis for testing at localhost:9736..."
40
- `redis-server #{dir}/redis-test.conf`
41
- Resque.redis = '127.0.0.1:9736'
42
+ puts "Starting redis for testing at localhost:9736..."
43
+ `redis-server #{dir}/redis-test.conf`
44
+ Resque.redis = '127.0.0.1:9736'
45
+ else
46
+ Resque.redis = '127.0.0.1:6379'
47
+ end
42
48
 
43
49
  # Test helpers
44
50
  class Minitest::Test
@@ -65,11 +71,11 @@ class Minitest::Test
65
71
 
66
72
  def delayed_jobs
67
73
  # The double-checks here are so that we won't blow up if the config stops using redis-namespace
68
- timestamps = Resque.redis.zrange("resque:delayed_queue_schedule", 0, -1) +
74
+ timestamps = Resque.redis.zrange("resque:delayed_queue_schedule", 0, -1) +
69
75
  Resque.redis.zrange("delayed_queue_schedule", 0, -1)
70
76
 
71
77
  delayed_jobs_as_json = timestamps.map do |timestamp|
72
- Resque.redis.lrange("resque:delayed:#{timestamp}", 0, -1) +
78
+ Resque.redis.lrange("resque:delayed:#{timestamp}", 0, -1) +
73
79
  Resque.redis.lrange("delayed:#{timestamp}", 0, -1)
74
80
  end.flatten
75
81
 
data/test/test_jobs.rb CHANGED
@@ -7,7 +7,7 @@ class NoRetryJob
7
7
  @queue = :testing
8
8
 
9
9
  def self.perform(*args)
10
- raise "error"
10
+ raise 'error'
11
11
  end
12
12
  end
13
13
 
@@ -28,6 +28,17 @@ class ExpiringJob
28
28
  end
29
29
  end
30
30
 
31
+ class ExpiringJobWithRetryExceptions
32
+ extend Resque::Plugins::Retry
33
+
34
+ @queue = :testing
35
+ @expire_retry_key_after = 10
36
+ @retry_exceptions = { StandardError => 7 }
37
+
38
+ def self.perform(*args)
39
+ end
40
+ end
41
+
31
42
  class RetryDefaultSettingsJob
32
43
  extend Resque::Plugins::Retry
33
44
  @queue = :testing
@@ -56,7 +67,7 @@ end
56
67
 
57
68
  class JobRetryQueue
58
69
  extend Resque::Plugins::Retry
59
- @queue = :testing_retry
70
+ @queue = :testing_retry_delegate
60
71
 
61
72
  def self.perform(*args)
62
73
  end
@@ -72,6 +83,50 @@ class JobWithRetryQueue
72
83
  end
73
84
  end
74
85
 
86
+ class JobWithDynamicRetryQueue
87
+ extend Resque::Plugins::Retry
88
+ @queue = :testing
89
+ @retry_delay = 1
90
+
91
+ def self.retry_queue(exception, *args)
92
+ args.first
93
+ end
94
+
95
+ def self.perform(*args)
96
+ raise
97
+ end
98
+ end
99
+
100
+ class DynamicDelayedJobOnExceptionAndArgs
101
+ extend Resque::Plugins::Retry
102
+ @queue = :testing
103
+
104
+ def self.retry_delay(exception, *args)
105
+ args.first.to_i
106
+ end
107
+
108
+ def self.perform(*args)
109
+ raise
110
+ end
111
+ end
112
+
113
+ class DynamicDelayedJobOnException
114
+ extend Resque::Plugins::Retry
115
+ @queue = :testing
116
+
117
+ def self.retry_delay(exception)
118
+ if exception == SocketError
119
+ 4
120
+ else
121
+ 1
122
+ end
123
+ end
124
+
125
+ def self.perform(*args)
126
+ raise SocketError
127
+ end
128
+ end
129
+
75
130
  class DelayedJobWithRetryQueue
76
131
  extend Resque::Plugins::Retry
77
132
  @queue = :testing
@@ -102,14 +157,6 @@ class InheritTestWithMoreExtraJob < InheritTestWithExtraJob
102
157
  end
103
158
  end
104
159
 
105
- class DeprecatedRetryWithModifiedArgsJob < RetryDefaultsJob
106
- @queue = :testing
107
-
108
- def self.args_for_retry(*args)
109
- # NOTE: implementation is irrelevant we only care that it's invoked
110
- end
111
- end
112
-
113
160
  class RetryWithModifiedArgsJob < RetryDefaultsJob
114
161
  @queue = :testing
115
162
 
@@ -207,6 +254,12 @@ class ExponentialBackoffWithRetryDelayMultiplicandMinAndMaxJob < RetryDefaultsJo
207
254
  @retry_delay_multiplicand_max = 3.0
208
255
  end
209
256
 
257
+ class ExponentialBackoffWithExpiryJob < RetryDefaultsJob
258
+ extend Resque::Plugins::ExponentialBackoff
259
+ @queue = :testing
260
+ @expire_retry_key_after = 60 * 60
261
+ end
262
+
210
263
  class InvalidRetryDelayMaxConfigurationJob
211
264
  @queue = :testing
212
265
  @retry_delay_multiplicand_max = 0.9
@@ -320,8 +373,15 @@ class BaseJob < AsyncJob
320
373
 
321
374
  def inherited(subclass)
322
375
  super
323
- %w(@retry_exceptions @retry_delay @retry_limit @auto_retry_limit).each do |variable|
324
- value = BaseJob.instance_variable_get(variable)
376
+ %i[
377
+ @auto_retry_limit
378
+ @retry_delay
379
+ @retry_exceptions
380
+ @retry_limit
381
+ ].each do |variable|
382
+ value = nil
383
+ value = BaseJob.instance_variable_get(variable) \
384
+ if BaseJob.instance_variable_defined?(variable)
325
385
  value = value.dup rescue value
326
386
  subclass.instance_variable_set(variable, value)
327
387
  end
@@ -483,6 +543,13 @@ class CustomRetryIdentifierFailingJob
483
543
  end
484
544
  end
485
545
 
546
+ class NoRetryDelayJob
547
+ extend Resque::Plugins::Retry
548
+
549
+ @queue = :testing
550
+ @retry_exceptions = {}
551
+ end
552
+
486
553
  class NormalRetryCountJob
487
554
  extend Resque::Plugins::Retry
488
555
 
@@ -496,7 +563,7 @@ class PerExceptionClassRetryCountJob
496
563
 
497
564
  @queue = :testing
498
565
  @retry_limit = 3
499
- @retry_exceptions = { RuntimeError => 7, Exception => 11, Timeout::Error => 13 }
566
+ @retry_exceptions = { StandardError => 7, AnotherCustomException => 11, HierarchyCustomException => 13 }
500
567
 
501
568
  def self.perform
502
569
  raise RuntimeError, 'I always fail with a RuntimeError'
@@ -515,6 +582,17 @@ class PerExceptionClassRetryCountArrayJob
515
582
  end
516
583
  end
517
584
 
585
+ class PerExceptionClassRetryCountArrayNoRetryLimitSpecifiedJob
586
+ extend Resque::Plugins::Retry
587
+
588
+ @queue = :testing
589
+ @retry_exceptions = { Exception => 11, RuntimeError => [5, 10, 15], Timeout::Error => [2, 4, 6, 8, 10] }
590
+
591
+ def self.perform
592
+ raise RuntimeError, 'I always fail with a RuntimeError'
593
+ end
594
+ end
595
+
518
596
  # We can't design a job to fail during connect, see perform_next_job_fail_on_reconnect
519
597
  class FailsDuringConnectJob < RetryDefaultsJob
520
598
  @queue = :testing
@@ -579,3 +657,15 @@ class RetryCallbacksJob
579
657
 
580
658
  give_up_callback :on_give_up_c
581
659
  end
660
+
661
+ class IgnoreExceptionsJob
662
+ extend Resque::Plugins::Retry
663
+ @queue = :testing
664
+ @ignore_exceptions = [CustomException]
665
+ @retry_exceptions = [CustomException, AnotherCustomException]
666
+ @retry_limit = 3
667
+
668
+ def self.perform
669
+ "Hello, World!"
670
+ end
671
+ end
metadata CHANGED
@@ -1,31 +1,37 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-retry
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.7.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luke Antins
8
8
  - Ryan Carver
9
9
  - Jonathan W. Zaleski
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-10-24 00:00:00.000000000 Z
13
+ date: 2021-08-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: resque
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - "~>"
19
+ - - ">="
20
20
  - !ruby/object:Gem::Version
21
21
  version: '1.25'
22
+ - - "<"
23
+ - !ruby/object:Gem::Version
24
+ version: '3.0'
22
25
  type: :runtime
23
26
  prerelease: false
24
27
  version_requirements: !ruby/object:Gem::Requirement
25
28
  requirements:
26
- - - "~>"
29
+ - - ">="
27
30
  - !ruby/object:Gem::Version
28
31
  version: '1.25'
32
+ - - "<"
33
+ - !ruby/object:Gem::Version
34
+ version: '3.0'
29
35
  - !ruby/object:Gem::Dependency
30
36
  name: resque-scheduler
31
37
  requirement: !ruby/object:Gem::Requirement
@@ -155,8 +161,8 @@ executables: []
155
161
  extensions: []
156
162
  extra_rdoc_files: []
157
163
  files:
164
+ - ".github/workflows/ci.yml"
158
165
  - ".gitignore"
159
- - ".travis.yml"
160
166
  - Gemfile
161
167
  - HISTORY.md
162
168
  - LICENSE
@@ -181,13 +187,17 @@ files:
181
187
  - lib/resque/plugins/retry/logging.rb
182
188
  - resque-retry.gemspec
183
189
  - test/exponential_backoff_test.rb
190
+ - test/ignore_exceptions_test.rb
184
191
  - test/multiple_failure_test.rb
185
192
  - test/redis-test.conf
193
+ - test/resque_inline_test.rb
186
194
  - test/resque_test.rb
187
195
  - test/retry_callbacks_test.rb
188
196
  - test/retry_criteria_test.rb
197
+ - test/retry_custom_delay_test.rb
189
198
  - test/retry_exception_delay_test.rb
190
199
  - test/retry_inheriting_checks_test.rb
200
+ - test/retry_queue_test.rb
191
201
  - test/retry_test.rb
192
202
  - test/server_helpers_test.rb
193
203
  - test/server_test.rb
@@ -198,7 +208,7 @@ homepage: http://github.com/lantins/resque-retry
198
208
  licenses:
199
209
  - MIT
200
210
  metadata: {}
201
- post_install_message:
211
+ post_install_message:
202
212
  rdoc_options: []
203
213
  require_paths:
204
214
  - lib
@@ -213,11 +223,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
213
223
  - !ruby/object:Gem::Version
214
224
  version: '0'
215
225
  requirements: []
216
- rubyforge_project:
217
- rubygems_version: 2.4.2
218
- signing_key:
226
+ rubygems_version: 3.2.22
227
+ signing_key:
219
228
  specification_version: 4
220
229
  summary: A resque plugin; provides retry, delay and exponential backoff support for
221
230
  resque jobs.
222
231
  test_files: []
223
- has_rdoc: false
data/.travis.yml DELETED
@@ -1,15 +0,0 @@
1
- language: ruby
2
-
3
- matrix:
4
- allow_failures:
5
- - rvm: jruby-19mode
6
- - rvm: rbx-2
7
-
8
- rvm:
9
- - 1.9.3
10
- - 2.0.0
11
- - 2.1.0
12
- - 2.1.1
13
- - 2.1.2
14
- - jruby-19mode
15
- - rbx-2