activejob-retry 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +5 -5
- data/lib/active_job/retry/constant_backoff_strategy.rb +9 -9
- data/lib/active_job/retry/constant_options_validator.rb +9 -6
- data/lib/active_job/retry/version.rb +1 -1
- data/spec/retry/constant_backoff_strategy_spec.rb +1 -1
- data/spec/retry/constant_options_validator_spec.rb +8 -8
- data/spec/retry/variable_backoff_strategy_spec.rb +1 -1
- data/spec/retry/variable_options_validator_spec.rb +8 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26e70483f72942ecc312de55cd5bd34280ff459a
|
4
|
+
data.tar.gz: 771d1365fd7fc7581fced033b642ef4188e2e88d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d486c2b1253b045158bdb2880c0b12a0a00ed3aa1d4378de4ce0420710ae8f5c9f775089ab44c80d122384bc3bbc1504cc42f678c6d473742ded17369108a9a6
|
7
|
+
data.tar.gz: d9a91dd6a4beb9687d47fe9ce3df82fc5c29516a09e9d2d699fd017f6dc7b9522abdabecd7224a2952029c6d15ec38281652a64494ddaa00ce8c471183d1598b
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -14,7 +14,7 @@ class ProcessWebhook < ActiveJob::Base
|
|
14
14
|
queue_as :webhooks
|
15
15
|
|
16
16
|
# Constant delay between attempts:
|
17
|
-
constant_retry limit: 3, delay: 5,
|
17
|
+
constant_retry limit: 3, delay: 5, retryable_exceptions: [TimeoutError, NetworkError]
|
18
18
|
|
19
19
|
# Or, variable delay between attempts:
|
20
20
|
variable_retry delays: [1, 5, 10, 30]
|
@@ -40,7 +40,7 @@ class ProcessWebhook < ActiveJob::Base
|
|
40
40
|
end
|
41
41
|
```
|
42
42
|
|
43
|
-
####
|
43
|
+
#### constant_retry options
|
44
44
|
`limit`
|
45
45
|
: Maximum number of times to attempt the job (default: 1).
|
46
46
|
|
@@ -50,13 +50,13 @@ end
|
|
50
50
|
`delay`
|
51
51
|
: Time between attempts (default: 0).
|
52
52
|
|
53
|
-
`
|
53
|
+
`retryable_exceptions`
|
54
54
|
: A whitelist of exceptions to retry (default: nil, i.e. all exceptions will result in a retry).
|
55
55
|
|
56
56
|
`fatal_exceptions`
|
57
57
|
: A blacklist of exceptions to not retry (default: []).
|
58
58
|
|
59
|
-
####
|
59
|
+
#### variable_retry options
|
60
60
|
|
61
61
|
`delays`
|
62
62
|
: __required__ An array of delays between attempts. The first attempt will occur whenever you originally enqueued the job to happen.
|
@@ -67,7 +67,7 @@ end
|
|
67
67
|
`max_delay_multiplier`
|
68
68
|
: The other end of the range for `min_delay_multiplier`. If one is supplied, both must be.
|
69
69
|
|
70
|
-
`
|
70
|
+
`retryable_exceptions`
|
71
71
|
: Same as for `constant_retry`.
|
72
72
|
|
73
73
|
`fatal_exceptions`
|
@@ -5,15 +5,15 @@ module ActiveJob
|
|
5
5
|
class ConstantBackoffStrategy
|
6
6
|
def initialize(options)
|
7
7
|
ConstantOptionsValidator.new(options).validate!
|
8
|
-
@retry_limit
|
9
|
-
@retry_delay
|
10
|
-
@fatal_exceptions
|
11
|
-
@
|
8
|
+
@retry_limit = options.fetch(:limit, 1)
|
9
|
+
@retry_delay = options.fetch(:delay, 0)
|
10
|
+
@fatal_exceptions = options.fetch(:fatal_exceptions, [])
|
11
|
+
@retryable_exceptions = options.fetch(:retryable_exceptions, nil)
|
12
12
|
end
|
13
13
|
|
14
14
|
def should_retry?(attempt, exception)
|
15
15
|
return false if retry_limit_reached?(attempt)
|
16
|
-
return false unless
|
16
|
+
return false unless retryable_exception?(exception)
|
17
17
|
true
|
18
18
|
end
|
19
19
|
|
@@ -23,15 +23,15 @@ module ActiveJob
|
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
|
-
attr_reader :retry_limit, :fatal_exceptions, :
|
26
|
+
attr_reader :retry_limit, :fatal_exceptions, :retryable_exceptions
|
27
27
|
|
28
28
|
def retry_limit_reached?(attempt)
|
29
29
|
return false unless retry_limit
|
30
30
|
attempt >= retry_limit
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
34
|
-
if
|
33
|
+
def retryable_exception?(exception)
|
34
|
+
if retryable_exceptions.nil?
|
35
35
|
!exception_blacklisted?(exception)
|
36
36
|
else
|
37
37
|
exception_whitelisted?(exception)
|
@@ -39,7 +39,7 @@ module ActiveJob
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def exception_whitelisted?(exception)
|
42
|
-
|
42
|
+
retryable_exceptions.any? { |ex| exception.is_a?(ex) }
|
43
43
|
end
|
44
44
|
|
45
45
|
def exception_blacklisted?(exception)
|
@@ -12,11 +12,14 @@ module ActiveJob
|
|
12
12
|
validate_infinite_limit!
|
13
13
|
validate_delay!
|
14
14
|
validate_not_both_exceptions!
|
15
|
-
# Fatal exceptions must be an array (cannot be nil, since then all
|
16
|
-
# would be fatal - for that just set `limit: 0`)
|
15
|
+
# Fatal exceptions must be an array (cannot be nil, since then all
|
16
|
+
# exceptions would be fatal - for that just set `limit: 0`)
|
17
17
|
validate_array_of_exceptions!(:fatal_exceptions)
|
18
|
-
#
|
19
|
-
|
18
|
+
# Retryable exceptions must be an array of exceptions or `nil` to retry
|
19
|
+
# any exception
|
20
|
+
if options[:retryable_exceptions]
|
21
|
+
validate_array_of_exceptions!(:retryable_exceptions)
|
22
|
+
end
|
20
23
|
end
|
21
24
|
|
22
25
|
private
|
@@ -56,10 +59,10 @@ module ActiveJob
|
|
56
59
|
end
|
57
60
|
|
58
61
|
def validate_not_both_exceptions!
|
59
|
-
return unless options[:fatal_exceptions] && options[:
|
62
|
+
return unless options[:fatal_exceptions] && options[:retryable_exceptions]
|
60
63
|
|
61
64
|
raise InvalidConfigurationError,
|
62
|
-
'fatal_exceptions and
|
65
|
+
'fatal_exceptions and retryable_exceptions cannot be used together'
|
63
66
|
end
|
64
67
|
|
65
68
|
def validate_array_of_exceptions!(key)
|
@@ -75,7 +75,7 @@ RSpec.describe ActiveJob::Retry::ConstantBackoffStrategy do
|
|
75
75
|
end
|
76
76
|
|
77
77
|
context 'with whitelist' do
|
78
|
-
let(:options) { { limit: 10,
|
78
|
+
let(:options) { { limit: 10, retryable_exceptions: [RuntimeError] } }
|
79
79
|
|
80
80
|
context 'Exception' do
|
81
81
|
let(:exception) { Exception.new }
|
@@ -25,18 +25,18 @@ RSpec.describe ActiveJob::Retry::ConstantOptionsValidator do
|
|
25
25
|
it { is_expected.to_not raise_error }
|
26
26
|
end
|
27
27
|
|
28
|
-
context '
|
28
|
+
context 'fatal_exceptions' do
|
29
29
|
let(:options) { { fatal_exceptions: [RuntimeError] } }
|
30
30
|
it { is_expected.to_not raise_error }
|
31
31
|
end
|
32
32
|
|
33
|
-
context '
|
34
|
-
let(:options) { {
|
33
|
+
context 'retryable_exceptions' do
|
34
|
+
let(:options) { { retryable_exceptions: [StandardError, NoMethodError] } }
|
35
35
|
it { is_expected.to_not raise_error }
|
36
36
|
end
|
37
37
|
|
38
38
|
context 'multiple options' do
|
39
|
-
let(:options) { { limit: 3, delay: 10,
|
39
|
+
let(:options) { { limit: 3, delay: 10, retryable_exceptions: [RuntimeError] } }
|
40
40
|
|
41
41
|
it { is_expected.to_not raise_error }
|
42
42
|
end
|
@@ -63,18 +63,18 @@ RSpec.describe ActiveJob::Retry::ConstantOptionsValidator do
|
|
63
63
|
it { is_expected.to raise_error(ActiveJob::Retry::InvalidConfigurationError) }
|
64
64
|
end
|
65
65
|
|
66
|
-
context 'bad
|
66
|
+
context 'bad fatal_exceptions' do
|
67
67
|
let(:options) { { fatal_exceptions: ['StandardError'] } }
|
68
68
|
it { is_expected.to raise_error(ActiveJob::Retry::InvalidConfigurationError) }
|
69
69
|
end
|
70
70
|
|
71
|
-
context 'bad
|
72
|
-
let(:options) { {
|
71
|
+
context 'bad retryable_exceptions' do
|
72
|
+
let(:options) { { retryable_exceptions: [:runtime] } }
|
73
73
|
it { is_expected.to raise_error(ActiveJob::Retry::InvalidConfigurationError) }
|
74
74
|
end
|
75
75
|
|
76
76
|
context 'retry and fatal exceptions together' do
|
77
|
-
let(:options) { { fatal_exceptions: [StandardError],
|
77
|
+
let(:options) { { fatal_exceptions: [StandardError], retryable_exceptions: [] } }
|
78
78
|
it { is_expected.to raise_error(ActiveJob::Retry::InvalidConfigurationError) }
|
79
79
|
end
|
80
80
|
end
|
@@ -61,7 +61,7 @@ RSpec.describe ActiveJob::Retry::VariableBackoffStrategy do
|
|
61
61
|
end
|
62
62
|
|
63
63
|
context 'with whitelist' do
|
64
|
-
let(:options) { { delays: [10],
|
64
|
+
let(:options) { { delays: [10], retryable_exceptions: [RuntimeError] } }
|
65
65
|
|
66
66
|
context 'Exception' do
|
67
67
|
let(:exception) { Exception.new }
|
@@ -27,13 +27,15 @@ RSpec.describe ActiveJob::Retry::VariableOptionsValidator do
|
|
27
27
|
it { is_expected.to_not raise_error }
|
28
28
|
end
|
29
29
|
|
30
|
-
context '
|
31
|
-
let(:options)
|
30
|
+
context 'retryable_exceptions' do
|
31
|
+
let(:options) do
|
32
|
+
{ delays: [], retryable_exceptions: [StandardError, NoMethodError] }
|
33
|
+
end
|
32
34
|
it { is_expected.to_not raise_error }
|
33
35
|
end
|
34
36
|
|
35
37
|
context 'multiple options' do
|
36
|
-
let(:options) { { delays: [0, 10, 60],
|
38
|
+
let(:options) { { delays: [0, 10, 60], retryable_exceptions: [RuntimeError] } }
|
37
39
|
|
38
40
|
it { is_expected.to_not raise_error }
|
39
41
|
end
|
@@ -70,13 +72,13 @@ RSpec.describe ActiveJob::Retry::VariableOptionsValidator do
|
|
70
72
|
it { is_expected.to raise_error(ActiveJob::Retry::InvalidConfigurationError) }
|
71
73
|
end
|
72
74
|
|
73
|
-
context 'bad
|
74
|
-
let(:options) { {
|
75
|
+
context 'bad retryable_exceptions' do
|
76
|
+
let(:options) { { retryable_exceptions: [:runtime] } }
|
75
77
|
it { is_expected.to raise_error(ActiveJob::Retry::InvalidConfigurationError) }
|
76
78
|
end
|
77
79
|
|
78
80
|
context 'retry and fatal exceptions together' do
|
79
|
-
let(:options) { { fatal_exceptions: [StandardError],
|
81
|
+
let(:options) { { fatal_exceptions: [StandardError], retryable_exceptions: [] } }
|
80
82
|
it { is_expected.to raise_error(ActiveJob::Retry::InvalidConfigurationError) }
|
81
83
|
end
|
82
84
|
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.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Isaac Seymour
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|