retryable 2.0.4 → 3.0.5
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 +7 -0
- data/CHANGELOG.md +35 -1
- data/Gemfile +20 -0
- data/README.md +136 -66
- data/Rakefile +2 -2
- data/lib/retryable/configuration.rb +18 -22
- data/lib/retryable/version.rb +33 -9
- data/lib/retryable.rb +48 -27
- data/retryable.gemspec +29 -18
- data/spec/retryable/configuration_spec.rb +55 -0
- data/spec/retryable/version_spec.rb +32 -0
- data/spec/retryable_logging_spec.rb +34 -0
- data/spec/retryable_spec.rb +192 -0
- data/spec/retryable_with_context_spec.rb +56 -0
- data/spec/spec_helper.rb +10 -17
- data/spec/support/counter.rb +58 -0
- metadata +53 -66
- data/spec/lib/configuration_spec.rb +0 -39
- data/spec/lib/retryable_spec.rb +0 -151
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Retryable do
|
4
|
-
it 'is enabled by default' do
|
5
|
-
expect(Retryable).to be_enabled
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'could be disabled' do
|
9
|
-
Retryable.disable
|
10
|
-
expect(Retryable).not_to be_enabled
|
11
|
-
end
|
12
|
-
|
13
|
-
context 'when disabled' do
|
14
|
-
before do
|
15
|
-
Retryable.disable
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'could be re-enabled' do
|
19
|
-
Retryable.enable
|
20
|
-
expect(Retryable).to be_enabled
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when configured globally with custom sleep parameter' do
|
25
|
-
it 'passes retry count and exception on retry' do
|
26
|
-
expect(Kernel).to receive(:sleep).once.with(3)
|
27
|
-
|
28
|
-
Retryable.configure do |config|
|
29
|
-
config.sleep = 3
|
30
|
-
end
|
31
|
-
|
32
|
-
count_retryable(:tries => 2) do |tries, ex|
|
33
|
-
expect(ex.class).to eq(StandardError) if tries > 0
|
34
|
-
raise StandardError if tries < 1
|
35
|
-
end
|
36
|
-
expect(@try_count).to eq(2)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/spec/lib/retryable_spec.rb
DELETED
@@ -1,151 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'timeout'
|
3
|
-
|
4
|
-
RSpec.describe 'Retryable.retryable' do
|
5
|
-
before(:each) do
|
6
|
-
Retryable.enable
|
7
|
-
@attempt = 0
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'catch StandardError only by default' do
|
11
|
-
expect do
|
12
|
-
count_retryable(:tries => 2) { |tries, ex| raise Exception if tries < 1 }
|
13
|
-
end.to raise_error Exception
|
14
|
-
expect(@try_count).to eq(1)
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'retries on default exception' do
|
18
|
-
expect(Kernel).to receive(:sleep).once.with(1)
|
19
|
-
|
20
|
-
count_retryable(:tries => 2) { |tries, ex| raise StandardError if tries < 1 }
|
21
|
-
expect(@try_count).to eq(2)
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'does not retry if disabled' do
|
25
|
-
Retryable.disable
|
26
|
-
|
27
|
-
expect do
|
28
|
-
count_retryable(:tries => 2) { raise }
|
29
|
-
end.to raise_error RuntimeError
|
30
|
-
expect(@try_count).to eq(1)
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'executes *ensure* clause' do
|
34
|
-
ensure_cb = Proc.new do |retries|
|
35
|
-
expect(retries).to eq(0)
|
36
|
-
end
|
37
|
-
|
38
|
-
Retryable.retryable(:ensure => ensure_cb) { }
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'passes retry count and exception on retry' do
|
42
|
-
expect(Kernel).to receive(:sleep).once.with(1)
|
43
|
-
|
44
|
-
count_retryable(:tries => 2) do |tries, ex|
|
45
|
-
expect(ex.class).to eq(StandardError) if tries > 0
|
46
|
-
raise StandardError if tries < 1
|
47
|
-
end
|
48
|
-
expect(@try_count).to eq(2)
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'makes another try if exception is covered by :on' do
|
52
|
-
allow(Kernel).to receive(:sleep)
|
53
|
-
count_retryable(:on => [StandardError, ArgumentError, RuntimeError] ) { |tries, ex| raise ArgumentError if tries < 1 }
|
54
|
-
expect(@try_count).to eq(2)
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'does not try on unexpected exception' do
|
58
|
-
allow(Kernel).to receive(:sleep)
|
59
|
-
expect do
|
60
|
-
count_retryable(:on => RuntimeError ) { |tries, ex| raise StandardError if tries < 1 }
|
61
|
-
end.to raise_error StandardError
|
62
|
-
expect(@try_count).to eq(1)
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'retries three times' do
|
66
|
-
allow(Kernel).to receive(:sleep)
|
67
|
-
count_retryable(:tries => 3) { |tries, ex| raise StandardError if tries < 2 }
|
68
|
-
expect(@try_count).to eq(3)
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'retries infinitely' do
|
72
|
-
expect do
|
73
|
-
Timeout::timeout(3) do
|
74
|
-
count_retryable(:tries => :infinite, :sleep => 0.1) { |tries, ex| raise StandardError }
|
75
|
-
end
|
76
|
-
end.to raise_error Timeout::Error
|
77
|
-
|
78
|
-
expect(@try_count).to be > 10
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'retries on default exception' do
|
82
|
-
expect(Kernel).to receive(:sleep).once.with(1)
|
83
|
-
|
84
|
-
count_retryable(:tries => 2) { |tries, ex| raise StandardError if tries < 1 }
|
85
|
-
expect(@try_count).to eq(2)
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'executes exponential backoff scheme for :sleep option' do
|
89
|
-
[1, 4, 16, 64].each { |i| expect(Kernel).to receive(:sleep).once.ordered.with(i) }
|
90
|
-
expect do
|
91
|
-
Retryable.retryable(:tries => 5, :sleep => lambda { |n| 4**n }) { raise RangeError }
|
92
|
-
end.to raise_error RangeError
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'calls :sleep_method option' do
|
96
|
-
sleep_method = double
|
97
|
-
expect(sleep_method).to receive(:call).twice
|
98
|
-
expect do
|
99
|
-
Retryable.retryable(:tries => 3, :sleep_method => sleep_method) { |tries, ex| raise RangeError if tries < 9}
|
100
|
-
end.to raise_error RangeError
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'does not retry any exception if :on is empty list' do
|
104
|
-
expect do
|
105
|
-
count_retryable(:on => []) { raise }
|
106
|
-
end.to raise_error RuntimeError
|
107
|
-
expect(@try_count).to eq(1)
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'catches an exception that matches the regex' do
|
111
|
-
expect(Kernel).to receive(:sleep).once.with(1)
|
112
|
-
count_retryable(:matching => /IO timeout/) { |c,e| raise "yo, IO timeout!" if c == 0 }
|
113
|
-
expect(@try_count).to eq(2)
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'does not catch an exception that does not match the regex' do
|
117
|
-
expect(Kernel).not_to receive(:sleep)
|
118
|
-
expect do
|
119
|
-
count_retryable(:matching => /TimeError/) { raise "yo, IO timeout!" }
|
120
|
-
end.to raise_error RuntimeError
|
121
|
-
expect(@try_count).to eq(1)
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'does not allow invalid options' do
|
125
|
-
expect do
|
126
|
-
Retryable.retryable(:bad_option => 2) { raise "this is bad" }
|
127
|
-
end.to raise_error ArgumentError, '[Retryable] Invalid options: bad_option'
|
128
|
-
end
|
129
|
-
|
130
|
-
it 'accepts a callback to run after an exception is rescued' do
|
131
|
-
expect do
|
132
|
-
Retryable.retryable(:sleep => 0, :exception_cb => Proc.new {|e| @raised = e.to_s }) {|tries, ex| raise StandardError.new("this is fun!") if tries < 1 }
|
133
|
-
end.not_to raise_error
|
134
|
-
|
135
|
-
expect(@raised).to eq("this is fun!")
|
136
|
-
end
|
137
|
-
|
138
|
-
it 'does not retry on :not exception' do
|
139
|
-
expect do
|
140
|
-
count_retryable(:not => RuntimeError ) { |tries, ex| raise RuntimeError if tries < 1 }
|
141
|
-
end.to raise_error RuntimeError
|
142
|
-
expect(@try_count).to eq(1)
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'gives precidence for :not over :on' do
|
146
|
-
expect do
|
147
|
-
count_retryable(:sleep => 0, :tries => 3, :on => StandardError, :not => IndexError ) { |tries, ex| raise tries >= 1 ? IndexError : StandardError }
|
148
|
-
end.to raise_error IndexError
|
149
|
-
expect(@try_count).to eq(2)
|
150
|
-
end
|
151
|
-
end
|