activejob-retry 0.6.2 → 0.6.3
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -3
- data/.travis.yml +10 -5
- data/CHANGELOG.md +13 -0
- data/Gemfile.activejob42 +3 -0
- data/Gemfile.activejob50 +3 -0
- data/README.md +38 -4
- data/lib/active_job/retry.rb +27 -7
- data/lib/active_job/retry/constant_options_validator.rb +1 -1
- data/lib/active_job/retry/exponential_options_validator.rb +1 -1
- data/lib/active_job/retry/version.rb +1 -1
- data/spec/retry_spec.rb +52 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4fbf3f8e2eee97ef30a65fdc9f627acb6fd9c271
|
4
|
+
data.tar.gz: 24c084bf1714043588bcd7643a39eabfdfe71d38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c62d03830fe93de1de6f04ae1e712c9098dd2e0ed029898faafad283406b8766f00a7f6b69c2de323176038149f48ca45a6759486f6f3109cfd9efca083b5ae3
|
7
|
+
data.tar.gz: '094302d4b6466df850e38a94af520c64d8141284bcde467ba66e71149a8113bd3527a0d9334b9dd95562b48895989e958a0a0a032afc8ca3129b9bf83c51d72d'
|
data/.rubocop.yml
CHANGED
@@ -12,9 +12,6 @@ LineLength:
|
|
12
12
|
Style/SignalException:
|
13
13
|
EnforcedStyle: 'only_raise'
|
14
14
|
|
15
|
-
Metrics/MethodLength:
|
16
|
-
CountComments: false
|
17
|
-
|
18
15
|
Style/Documentation:
|
19
16
|
Enabled: false
|
20
17
|
|
@@ -23,3 +20,12 @@ Style/DotPosition:
|
|
23
20
|
|
24
21
|
Style/GuardClause:
|
25
22
|
Enabled: false
|
23
|
+
|
24
|
+
Metrics/MethodLength:
|
25
|
+
CountComments: false
|
26
|
+
|
27
|
+
Metrics/BlockLength:
|
28
|
+
CountComments: false
|
29
|
+
Exclude:
|
30
|
+
- Rakefile
|
31
|
+
- spec/**/*
|
data/.travis.yml
CHANGED
@@ -6,21 +6,26 @@ language: ruby
|
|
6
6
|
matrix:
|
7
7
|
exclude:
|
8
8
|
# Rails 5.0 dropped support for Ruby <2.2
|
9
|
-
- rvm: 2.0
|
10
|
-
gemfile: Gemfile.activejob50
|
11
9
|
- rvm: 2.1
|
12
10
|
gemfile: Gemfile.activejob50
|
11
|
+
# Rails 4-2-stable supports Ruby 2.4, but the released version doesn't. Ignore for now.
|
12
|
+
- rvm: 2.4.0
|
13
|
+
gemfile: Gemfile.activejob42
|
13
14
|
|
14
15
|
rvm:
|
15
|
-
- 2.0
|
16
16
|
- 2.1
|
17
17
|
- 2.2.2
|
18
|
-
- 2.3.
|
18
|
+
- 2.3.3
|
19
|
+
- 2.4.0
|
19
20
|
|
20
21
|
gemfile:
|
21
22
|
- Gemfile.activejob42
|
22
23
|
- Gemfile.activejob50
|
23
24
|
|
25
|
+
before_install:
|
26
|
+
- gem update --system
|
27
|
+
- gem install bundler
|
28
|
+
|
24
29
|
script:
|
25
30
|
- bundle exec rubocop
|
26
31
|
- bundle exec rspec spec
|
@@ -31,4 +36,4 @@ services:
|
|
31
36
|
- rabbitmq
|
32
37
|
|
33
38
|
addons:
|
34
|
-
postgresql: "9.
|
39
|
+
postgresql: "9.6"
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## 0.6.3 - Feb 9, 2017
|
2
|
+
|
3
|
+
- Add `callback` option, to be run before each retry, and potentially cancel the retry (by
|
4
|
+
[@doits](https://github.com/doits))
|
5
|
+
|
6
|
+
## 0.6.2 - Aug 10, 2016
|
7
|
+
|
8
|
+
- Rails 5 support (by [@isaacseymour](https://github.com/isaacseymour))
|
9
|
+
|
10
|
+
## 0.6.1 - Jun 1, 2016
|
11
|
+
|
12
|
+
- Apply retry settings to subclasses (by [@isaacseymour](https://github.com/isaacseymour))
|
13
|
+
|
1
14
|
## 0.6.0 - May 18, 2016
|
2
15
|
|
3
16
|
- Change API usage to make improper use harder (by [@isaacseymour](https://github.com/isaacseymour))
|
data/Gemfile.activejob42
CHANGED
data/Gemfile.activejob50
CHANGED
data/README.md
CHANGED
@@ -65,7 +65,6 @@ if the exception is not going to be retried, or has failed the final retry.
|
|
65
65
|
| `fatal_exceptions` | `[]` | Same as for [constant](#constant-options).
|
66
66
|
|
67
67
|
#### variable options
|
68
|
-
|
69
68
|
| Option | Default | Description |
|
70
69
|
|:---------------------- |:------- |:------------- |
|
71
70
|
| `delays` | | __required__ An array of delays between attempts in seconds. The first attempt will occur whenever you originally enqueued the job to happen.
|
@@ -74,6 +73,42 @@ if the exception is not going to be retried, or has failed the final retry.
|
|
74
73
|
| `retryable_exceptions` | `nil` | Same as for [constant](#constant-options).
|
75
74
|
| `fatal_exceptions` | `[]` | Same as for [constant](#constant-options).
|
76
75
|
|
76
|
+
## Callback
|
77
|
+
|
78
|
+
All strategies support a `callback` option:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
class ProcessWebhook < ActiveJob::Base
|
82
|
+
include ActiveJob::Retry.new(
|
83
|
+
strategy: :exponential, limit: 25,
|
84
|
+
callback: proc do |exception, delay|
|
85
|
+
# will be run before each retry
|
86
|
+
end
|
87
|
+
)
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
`callback` must be a `proc` and is run before each retry. It receives the
|
92
|
+
exception and delay before the next retry as arguments. It is evaluated on
|
93
|
+
instance level, so you have access to all instance variables and methods (for
|
94
|
+
example `retry_attempt`) of your job.
|
95
|
+
|
96
|
+
If the callback returns `:halt`, retry chain is halted and no further retries
|
97
|
+
will be made:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
class ProcessWebhook < ActiveJob::Base
|
101
|
+
include ActiveJob::Retry.new(
|
102
|
+
strategy: :exponential, limit: 25,
|
103
|
+
callback: proc do |exception, delay|
|
104
|
+
if some_condition
|
105
|
+
:halt # this will halt the retry chain
|
106
|
+
end
|
107
|
+
end
|
108
|
+
)
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
77
112
|
## Supported backends
|
78
113
|
|
79
114
|
Any queue adapter which supports delayed enqueuing (i.e. the `enqueue_at`
|
@@ -121,9 +156,8 @@ ActiveJob jobs.
|
|
121
156
|
Supported Versions
|
122
157
|
------------------
|
123
158
|
|
124
|
-
Rails 4.2 and 5.0 are supported,
|
125
|
-
|
126
|
-
tested in Travis CI.
|
159
|
+
Rails 4.2 and 5.0 are supported, Ruby 2.1+. Other Ruby runtimes (e.g. JRuby,
|
160
|
+
Rubinius) probably work, but are not tested in Travis CI.
|
127
161
|
|
128
162
|
Contributing
|
129
163
|
------------
|
data/lib/active_job/retry.rb
CHANGED
@@ -32,15 +32,12 @@ module ActiveJob
|
|
32
32
|
#################
|
33
33
|
# Configuration #
|
34
34
|
#################
|
35
|
-
def initialize(strategy: nil, **options)
|
35
|
+
def initialize(strategy: nil, callback: nil, **options)
|
36
36
|
check_adapter!
|
37
37
|
@backoff_strategy = choose_strategy(strategy, options)
|
38
|
+
@retry_callback = callback
|
38
39
|
|
39
|
-
|
40
|
-
raise InvalidConfigurationError,
|
41
|
-
'Backoff strategies must define `should_retry?(attempt, exception)`, ' \
|
42
|
-
'and `retry_delay(attempt, exception)`.'
|
43
|
-
end
|
40
|
+
validate_params
|
44
41
|
end
|
45
42
|
|
46
43
|
def included(base)
|
@@ -52,11 +49,12 @@ module ActiveJob
|
|
52
49
|
define_retry_attempt_tracking(base)
|
53
50
|
define_retry_method(base)
|
54
51
|
define_retry_logic(base)
|
52
|
+
define_retry_callback(base)
|
55
53
|
end
|
56
54
|
|
57
55
|
private
|
58
56
|
|
59
|
-
attr_reader :backoff_strategy
|
57
|
+
attr_reader :backoff_strategy, :retry_callback
|
60
58
|
|
61
59
|
def define_backoff_strategy(klass)
|
62
60
|
klass.instance_variable_set(:@backoff_strategy, @backoff_strategy)
|
@@ -80,6 +78,11 @@ module ActiveJob
|
|
80
78
|
klass.instance_eval do
|
81
79
|
define_method :internal_retry do |exception|
|
82
80
|
this_delay = self.class.backoff_strategy.retry_delay(retry_attempt, exception)
|
81
|
+
|
82
|
+
cb = self.class.retry_callback &&
|
83
|
+
instance_exec(exception, this_delay, &self.class.retry_callback)
|
84
|
+
return if cb == :halt
|
85
|
+
|
83
86
|
# TODO: This breaks DelayedJob and Resque for some weird ActiveSupport reason.
|
84
87
|
# logger.info("Retrying (attempt #{retry_attempt + 1}, waiting #{this_delay}s)")
|
85
88
|
@retry_attempt += 1
|
@@ -103,6 +106,11 @@ module ActiveJob
|
|
103
106
|
end
|
104
107
|
end
|
105
108
|
|
109
|
+
def define_retry_callback(klass)
|
110
|
+
klass.instance_variable_set(:@retry_callback, @retry_callback)
|
111
|
+
klass.define_singleton_method(:retry_callback) { @retry_callback }
|
112
|
+
end
|
113
|
+
|
106
114
|
def check_adapter!
|
107
115
|
adapter = ActiveJob::Base.queue_adapter
|
108
116
|
adapter_name =
|
@@ -117,6 +125,18 @@ module ActiveJob
|
|
117
125
|
end
|
118
126
|
end
|
119
127
|
|
128
|
+
def validate_params
|
129
|
+
if retry_callback && !retry_callback.is_a?(Proc)
|
130
|
+
raise InvalidConfigurationError, 'Callback must be a `Proc`'
|
131
|
+
end
|
132
|
+
|
133
|
+
unless backoff_strategy_valid?
|
134
|
+
raise InvalidConfigurationError,
|
135
|
+
'Backoff strategies must define `should_retry?(attempt, exception)`, ' \
|
136
|
+
'and `retry_delay(attempt, exception)`.'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
120
140
|
def backoff_strategy_valid?
|
121
141
|
backoff_strategy.respond_to?(:should_retry?) &&
|
122
142
|
backoff_strategy.respond_to?(:retry_delay) &&
|
@@ -29,7 +29,7 @@ module ActiveJob
|
|
29
29
|
# Limit must be an integer >= 0, or nil
|
30
30
|
def validate_limit_numericality!
|
31
31
|
return unless options[:limit]
|
32
|
-
return if options[:limit].is_a?(
|
32
|
+
return if options[:limit].is_a?(Integer) && options[:limit] >= 0
|
33
33
|
|
34
34
|
raise InvalidConfigurationError,
|
35
35
|
'Limit must be an integer >= 0, or nil for unlimited retries'
|
@@ -29,7 +29,7 @@ module ActiveJob
|
|
29
29
|
# Limit must be an integer >= 0, or nil
|
30
30
|
def validate_limit_numericality!
|
31
31
|
return unless options[:limit]
|
32
|
-
return if options[:limit].is_a?(
|
32
|
+
return if options[:limit].is_a?(Integer) && options[:limit] >= 0
|
33
33
|
|
34
34
|
raise InvalidConfigurationError,
|
35
35
|
'Limit must be an integer >= 0, or nil for unlimited retries'
|
data/spec/retry_spec.rb
CHANGED
@@ -295,4 +295,56 @@ RSpec.describe ActiveJob::Retry do
|
|
295
295
|
end
|
296
296
|
end
|
297
297
|
end
|
298
|
+
|
299
|
+
describe 'retry callback' do
|
300
|
+
let(:retry_instance) do
|
301
|
+
described_class.new(strategy: :constant, callback: callback, **options)
|
302
|
+
end
|
303
|
+
let(:callback_double) { double(call: nil) }
|
304
|
+
let(:callback) { callback_double.method(:call).to_proc }
|
305
|
+
let(:instance) { job.new }
|
306
|
+
subject(:perform) { instance.perform_now }
|
307
|
+
|
308
|
+
context 'invalid options' do
|
309
|
+
let(:callback) { 'not a proc' }
|
310
|
+
|
311
|
+
specify do
|
312
|
+
expect { retry_instance }.
|
313
|
+
to raise_error(ActiveJob::Retry::InvalidConfigurationError)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context 'when the job should be retried' do
|
318
|
+
before do
|
319
|
+
expect(job.backoff_strategy).to receive(:should_retry?).
|
320
|
+
with(1, instance_of(RuntimeError)).
|
321
|
+
and_return(true)
|
322
|
+
end
|
323
|
+
|
324
|
+
it 'executes callback proc on retry' do
|
325
|
+
expect(callback_double).to receive(:call)
|
326
|
+
perform
|
327
|
+
end
|
328
|
+
|
329
|
+
context 'with callback returning :halt' do
|
330
|
+
let(:callback) { proc { :halt } }
|
331
|
+
|
332
|
+
it 'it does not retry the job' do
|
333
|
+
expect(instance).not_to receive(:retry_job)
|
334
|
+
|
335
|
+
perform
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
context 'with callback not returning :halt' do
|
340
|
+
let(:callback) { proc { 'not halt' } }
|
341
|
+
|
342
|
+
it 'it retries the job' do
|
343
|
+
expect(instance).to receive(:retry_job)
|
344
|
+
|
345
|
+
perform
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
298
350
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activejob-retry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Isaac Seymour
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|
@@ -200,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
200
200
|
version: '0'
|
201
201
|
requirements: []
|
202
202
|
rubyforge_project:
|
203
|
-
rubygems_version: 2.
|
203
|
+
rubygems_version: 2.6.10
|
204
204
|
signing_key:
|
205
205
|
specification_version: 4
|
206
206
|
summary: Automatic retry functionality for ActiveJob.
|