retriable 2.0.0.beta1 → 2.0.0.beta2
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/.travis.yml +1 -1
- data/CHANGELOG.md +4 -0
- data/README.md +7 -4
- data/lib/retriable.rb +4 -3
- data/lib/retriable/version.rb +1 -1
- data/spec/retriable_spec.rb +133 -64
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b252298dcbaede9a87149f78cec0c067742b1167
|
4
|
+
data.tar.gz: b58875b898c832a5bd8ae3fd20d2eb62f80c7f84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e216f86b87a3526982647c8a2c6d8733eb7c9e3f4e7a262f3f38ead6d36bd4bd3c494ef22409cdf06e195de23360eb6d5f12cfa1c4c0de2492c03c49f17fe005
|
7
|
+
data.tar.gz: 43505f1550318db78adcb85dd1c023280ca9b7be802ec3a331e56ae094648a9fcfd2b5879bfc90ddf840e13a3ce29e96c28e7a33cb5e12abaddf89f9a32f82c7
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## 2.0.0.beta2
|
2
|
+
* Raise not return on max elapsed time, also check for elapsed time after next interval is calculated and it goes over the max elapsed time
|
3
|
+
* Add specs for max_elapsed_time and max_interval
|
4
|
+
|
1
5
|
## 2.0.0.beta1
|
2
6
|
* Require ruby 2.0+.
|
3
7
|
* Default to random exponential backoff, removes the `interval` option. Exponential backoff is configurable via arguments.
|
data/README.md
CHANGED
@@ -70,8 +70,11 @@ Here are the available options:
|
|
70
70
|
|
71
71
|
`max_interval` (default: 60) - The maximum interval in seconds that any attempt can climb to.
|
72
72
|
|
73
|
-
`rand_factor` (default: 0.25) - The percent range above and below the next interval is randomized between. The calculation is calculated like this:
|
74
|
-
|
73
|
+
`rand_factor` (default: 0.25) - The percent range above and below the next interval is randomized between. The calculation is calculated like this:
|
74
|
+
|
75
|
+
```
|
76
|
+
randomized_interval = retry_interval * (random value in range [1 - randomization_factor, 1 + randomization_factor])
|
77
|
+
```
|
75
78
|
|
76
79
|
`multiplier` (default: 1.5) - Each successive interval grows by this factor. A multipler of 1.5 means the next interval will be 1.5x the current interval.
|
77
80
|
|
@@ -133,7 +136,7 @@ end
|
|
133
136
|
Exponential backoff is enabled by default, if you want to simply execute code every second, you can do this:
|
134
137
|
|
135
138
|
```ruby
|
136
|
-
Retriable.
|
139
|
+
Retriable.retry base_interval: 1.0, multiplier: 1.0, rand_factor: 0.0 do
|
137
140
|
# code here...
|
138
141
|
end
|
139
142
|
```
|
@@ -141,7 +144,7 @@ end
|
|
141
144
|
If you don't want exponential backoff, but you still want some randomization between intervals, this code will run every 1 seconds with a randomization factor of 0.2, which means each interval will be a random value between 0.8 and 1.2 (1 second +/- 0.2):
|
142
145
|
|
143
146
|
```ruby
|
144
|
-
Retriable.
|
147
|
+
Retriable.retry base_interval: 1.0, multiplier: 1.0, rand_factor: 0.2 do
|
145
148
|
# code here...
|
146
149
|
end
|
147
150
|
```
|
data/lib/retriable.rb
CHANGED
@@ -27,8 +27,9 @@ module Retriable
|
|
27
27
|
raise LocalJumpError unless block_given?
|
28
28
|
|
29
29
|
attempt = 0
|
30
|
-
start_time = Time.now
|
31
30
|
interval = base_interval
|
31
|
+
start_time = Time.now
|
32
|
+
elapsed_time = lambda { Time.now - start_time }
|
32
33
|
|
33
34
|
begin
|
34
35
|
attempt += 1
|
@@ -40,12 +41,12 @@ module Retriable
|
|
40
41
|
rescue *[*on] => exception
|
41
42
|
raise if attempt >= max_tries
|
42
43
|
|
43
|
-
return if (Time.now - start_time) > max_elapsed_time
|
44
|
-
|
45
44
|
interval = randomized_interval(rand_factor, interval)
|
46
45
|
|
47
46
|
on_retry.call(exception, attempt, Time.now - start_time, interval) if on_retry
|
48
47
|
|
48
|
+
raise if elapsed_time.call > max_elapsed_time || (elapsed_time.call + interval) > max_elapsed_time
|
49
|
+
|
49
50
|
sleep interval if interval > 0 && config.sleep_disabled != true
|
50
51
|
|
51
52
|
interval = if interval >= (max_interval / multiplier)
|
data/lib/retriable/version.rb
CHANGED
data/spec/retriable_spec.rb
CHANGED
@@ -7,105 +7,174 @@ describe Retriable do
|
|
7
7
|
Retriable
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
describe 'with sleep disabled' do
|
11
|
+
before do
|
12
|
+
Retriable.configure do |c|
|
13
|
+
c.sleep_disabled = true
|
14
|
+
end
|
13
15
|
end
|
14
|
-
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
it 'raises a LocalJumpError if retry is not given a block' do
|
18
|
+
lambda do
|
19
|
+
subject.retry on: EOFError
|
20
|
+
end.must_raise LocalJumpError
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
describe 'retry block of code raising EOFError with no arguments' do
|
24
|
+
before do
|
25
|
+
@attempts = 0
|
26
|
+
|
27
|
+
subject.retry do
|
28
|
+
@attempts += 1
|
29
|
+
raise EOFError.new if @attempts < 3
|
30
|
+
end
|
31
|
+
end
|
25
32
|
|
26
|
-
|
27
|
-
@attempts
|
28
|
-
raise EOFError.new if @attempts < 3
|
33
|
+
it 'uses exponential backoff' do
|
34
|
+
@attempts.must_equal 3
|
29
35
|
end
|
30
36
|
end
|
31
37
|
|
32
|
-
it '
|
33
|
-
|
38
|
+
it 'retry on custom exception and re-raises the exception' do
|
39
|
+
lambda do
|
40
|
+
subject.retry on: TestError do
|
41
|
+
raise TestError.new
|
42
|
+
end
|
43
|
+
end.must_raise TestError
|
34
44
|
end
|
35
|
-
end
|
36
45
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
46
|
+
it 'retry with 10 max tries' do
|
47
|
+
attempts = 0
|
48
|
+
|
49
|
+
subject.retry(
|
50
|
+
max_tries: 10
|
51
|
+
) do
|
52
|
+
attempts += 1
|
53
|
+
raise EOFError.new if attempts < 10
|
41
54
|
end
|
42
|
-
end.must_raise TestError
|
43
|
-
end
|
44
55
|
|
45
|
-
|
46
|
-
|
56
|
+
attempts.must_equal 10
|
57
|
+
end
|
47
58
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
59
|
+
it 'retry will timeout after 1 second' do
|
60
|
+
lambda do
|
61
|
+
subject.retry timeout: 1 do
|
62
|
+
sleep 2
|
63
|
+
end
|
64
|
+
end.must_raise Timeout::Error
|
53
65
|
end
|
54
66
|
|
55
|
-
|
56
|
-
|
67
|
+
describe 'retries with an on_retry handler, 6 max retries, and a 0.0 rand_factor' do
|
68
|
+
before do
|
69
|
+
max_tries = 6
|
70
|
+
@attempts = 0
|
71
|
+
@time_table = {}
|
72
|
+
|
73
|
+
handler = Proc.new do |exception, attempt, elapsed_time, next_interval|
|
74
|
+
exception.class.must_equal ArgumentError
|
75
|
+
@time_table[attempt] = next_interval
|
76
|
+
end
|
77
|
+
|
78
|
+
Retriable.retry(
|
79
|
+
on: [EOFError, ArgumentError],
|
80
|
+
on_retry: handler,
|
81
|
+
rand_factor: 0.0,
|
82
|
+
max_tries: max_tries
|
83
|
+
) do
|
84
|
+
@attempts += 1
|
85
|
+
raise ArgumentError.new if @attempts < max_tries
|
86
|
+
end
|
87
|
+
end
|
57
88
|
|
58
|
-
|
59
|
-
|
89
|
+
it 'makes 6 attempts' do
|
90
|
+
@attempts.must_equal 6
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'applies a non-randomized exponential backoff to each attempt' do
|
94
|
+
@time_table.must_equal({
|
95
|
+
1 => 0.5,
|
96
|
+
2 => 0.75,
|
97
|
+
3 => 1.125,
|
98
|
+
4 => 1.6875,
|
99
|
+
5 => 2.53125
|
100
|
+
})
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'retry has a max interval of 1.5 seconds' do
|
60
105
|
max_tries = 6
|
61
|
-
|
62
|
-
|
106
|
+
attempts = 0
|
107
|
+
time_table = {}
|
63
108
|
|
64
109
|
handler = Proc.new do |exception, attempt, elapsed_time, next_interval|
|
65
|
-
|
66
|
-
@time_table[attempt] = next_interval
|
110
|
+
time_table[attempt] = next_interval
|
67
111
|
end
|
68
112
|
|
69
|
-
|
70
|
-
on:
|
113
|
+
subject.retry(
|
114
|
+
on: EOFError,
|
71
115
|
on_retry: handler,
|
72
116
|
rand_factor: 0.0,
|
73
|
-
max_tries: max_tries
|
117
|
+
max_tries: max_tries,
|
118
|
+
max_interval: 1.5
|
74
119
|
) do
|
75
|
-
|
76
|
-
raise
|
120
|
+
attempts += 1
|
121
|
+
raise EOFError.new if attempts < max_tries
|
77
122
|
end
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'makes 6 attempts' do
|
81
|
-
@attempts.must_equal 6
|
82
|
-
end
|
83
123
|
|
84
|
-
|
85
|
-
@time_table.must_equal({
|
124
|
+
time_table.must_equal({
|
86
125
|
1 => 0.5,
|
87
126
|
2 => 0.75,
|
88
127
|
3 => 1.125,
|
89
|
-
4 => 1.
|
90
|
-
5 =>
|
128
|
+
4 => 1.5,
|
129
|
+
5 => 1.5
|
91
130
|
})
|
92
131
|
end
|
93
|
-
end
|
94
132
|
|
95
|
-
|
96
|
-
|
133
|
+
it 'can call #retriable in the global' do
|
134
|
+
lambda do
|
135
|
+
retriable do
|
136
|
+
puts 'should raise NoMethodError'
|
137
|
+
end
|
138
|
+
end.must_raise NoMethodError
|
139
|
+
|
140
|
+
require_relative '../lib/retriable/core_ext/kernel'
|
141
|
+
|
142
|
+
i = 0
|
97
143
|
retriable do
|
98
|
-
|
144
|
+
i += 1
|
145
|
+
raise EOFError.new if i < 3
|
99
146
|
end
|
100
|
-
|
147
|
+
i.must_equal 3
|
148
|
+
end
|
149
|
+
end
|
101
150
|
|
102
|
-
|
151
|
+
it 'retry runs for a max elapsed time of 2 seconds' do
|
152
|
+
subject.configure do |c|
|
153
|
+
c.sleep_disabled = false
|
154
|
+
end
|
155
|
+
|
156
|
+
subject.config.sleep_disabled.must_equal false
|
157
|
+
|
158
|
+
attempts = 0
|
159
|
+
time_table = {}
|
103
160
|
|
104
|
-
|
105
|
-
|
106
|
-
i += 1
|
107
|
-
raise EOFError.new if i < 3
|
161
|
+
handler = Proc.new do |exception, attempt, elapsed_time, next_interval|
|
162
|
+
time_table[attempt] = elapsed_time
|
108
163
|
end
|
109
|
-
|
164
|
+
|
165
|
+
lambda do
|
166
|
+
subject.retry(
|
167
|
+
base_interval: 1.0,
|
168
|
+
multiplier: 1.0,
|
169
|
+
rand_factor: 0.0,
|
170
|
+
max_elapsed_time: 2.0,
|
171
|
+
on_retry: handler
|
172
|
+
) do
|
173
|
+
attempts += 1
|
174
|
+
raise EOFError.new
|
175
|
+
end
|
176
|
+
end.must_raise EOFError
|
177
|
+
|
178
|
+
attempts.must_equal 2
|
110
179
|
end
|
111
180
|
end
|