take2 0.0.5 → 0.1.0
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/Gemfile.lock +1 -1
- data/README.md +8 -2
- data/lib/take2.rb +34 -31
- data/lib/take2/version.rb +1 -1
- data/spec/take2_spec.rb +92 -94
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2b9d1165c2bbc7d0e0e59b161ef35e9d72586f8498738312bf72ebf5e5b2f31
|
4
|
+
data.tar.gz: 1b4d00168ff6b2cdc14be86fcf65b05e0ff919ca4e61535e76cdd3fac0006680
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f01b351dd0a3640fd09d7fe00b515543bbbfaf9ec1abb60bbf2b962e20b32490edb06cab51b81ee65383864e90f92e54533639a1bed1eaae1ed24afe599e378
|
7
|
+
data.tar.gz: 853ffe970c1c08306ff42966d7946ed92445e7d6b999801eeedf9ff2eae4f0ef12e321ff9ab75a2ce22d9514af5797d497c9f090dfee4aa4be7e7a7809911e64
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -30,7 +30,12 @@ class KratosService
|
|
30
30
|
# Defines callable code to run before next retry. Could be an out put to some logger.
|
31
31
|
on_retry proc { |error, tries| puts "#{self.name} - Retrying.. #{tries} of #{self.retriable_configuration[:retries]} (#{error})" }
|
32
32
|
|
33
|
-
|
33
|
+
# The available strategies are:
|
34
|
+
# type :constant, start: 2 => [2, 2, 2, 2 ... ]
|
35
|
+
# type :linear, start: 3, factor: 2 => [3, 6, 12, 24 ... ]
|
36
|
+
# type :fibonacci, start: 2 => [2, 3, 5, 8, 13 ... ]
|
37
|
+
# type :exponential, start: 3 => [3, 7, 12, 28, 47 ... ]
|
38
|
+
backoff_strategy type: :fibonacci, start: 3
|
34
39
|
|
35
40
|
def call_boy
|
36
41
|
call_api_with_retry do
|
@@ -45,7 +50,7 @@ class KratosService
|
|
45
50
|
# Pass custom options per method call
|
46
51
|
# The class defaults will not be overwritten
|
47
52
|
def kill_baldur
|
48
|
-
call_api_with_retry(retries: 2, retriable: [IOError], retry_proc: proc {}, retry_condition_proc: proc {}
|
53
|
+
call_api_with_retry(retries: 2, retriable: [IOError], retry_proc: proc {}, retry_condition_proc: proc {}) do
|
49
54
|
# Some logic that might raise..
|
50
55
|
end
|
51
56
|
end
|
@@ -88,5 +93,6 @@ Take2.configure do |config|
|
|
88
93
|
config.retry_condition_proc = proc {false}
|
89
94
|
config.time_to_sleep = nil
|
90
95
|
config.retry_proc = proc {Rails.logger.info "Retry message"}
|
96
|
+
config.backoff_intervals = Take2::Backoff.new(:linear, 1).intervals
|
91
97
|
end
|
92
98
|
```
|
data/lib/take2.rb
CHANGED
@@ -13,22 +13,22 @@ module Take2
|
|
13
13
|
|
14
14
|
class << self
|
15
15
|
attr_accessor :configuration
|
16
|
-
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def config
|
18
|
+
@configuration ||= Configuration.new
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
def reset(options = {})
|
22
|
+
@configuration = Configuration.new(options)
|
23
|
+
end
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
def local_defaults(options)
|
26
|
+
configuration.validate_options(options)
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
29
|
+
def configure
|
30
|
+
yield(config) if block_given?
|
31
|
+
end
|
32
32
|
end
|
33
33
|
|
34
34
|
module InstanceMethods
|
@@ -56,8 +56,16 @@ module Take2
|
|
56
56
|
# end
|
57
57
|
#
|
58
58
|
# end
|
59
|
+
def call_api_with_retry(options = {}, &block)
|
60
|
+
self.class.call_api_with_retry(options, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
alias_method :with_retry, :call_api_with_retry
|
64
|
+
end
|
65
|
+
|
66
|
+
module ClassMethods
|
59
67
|
def call_api_with_retry(options = {})
|
60
|
-
config =
|
68
|
+
config = retriable_configuration
|
61
69
|
config.merge!(Take2.local_defaults(options)) unless options.empty?
|
62
70
|
tries ||= config[:retries]
|
63
71
|
begin
|
@@ -74,25 +82,7 @@ module Take2
|
|
74
82
|
raise e
|
75
83
|
end
|
76
84
|
end
|
77
|
-
alias_method :with_retry, :call_api_with_retry
|
78
85
|
|
79
|
-
private
|
80
|
-
|
81
|
-
def rest(config, tries)
|
82
|
-
seconds = if config[:time_to_sleep].to_f > 0
|
83
|
-
config[:time_to_sleep].to_f
|
84
|
-
else
|
85
|
-
next_interval(config[:backoff_intervals], config[:retries], tries)
|
86
|
-
end
|
87
|
-
sleep(seconds)
|
88
|
-
end
|
89
|
-
|
90
|
-
def next_interval(intervals, retries, current)
|
91
|
-
intervals[retries - current]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
module ClassMethods
|
96
86
|
# Sets number of retries.
|
97
87
|
#
|
98
88
|
# Example:
|
@@ -197,5 +187,18 @@ module Take2
|
|
197
187
|
return response.status if response.respond_to?(:status)
|
198
188
|
response.status_code if response.respond_to?(:status_code)
|
199
189
|
end
|
190
|
+
|
191
|
+
def rest(config, tries)
|
192
|
+
seconds = if config[:time_to_sleep].to_f > 0
|
193
|
+
config[:time_to_sleep].to_f
|
194
|
+
else
|
195
|
+
next_interval(config[:backoff_intervals], config[:retries], tries)
|
196
|
+
end
|
197
|
+
sleep(seconds)
|
198
|
+
end
|
199
|
+
|
200
|
+
def next_interval(intervals, retries, current)
|
201
|
+
intervals[retries - current]
|
202
|
+
end
|
200
203
|
end
|
201
204
|
end
|
data/lib/take2/version.rb
CHANGED
data/spec/take2_spec.rb
CHANGED
@@ -151,132 +151,130 @@ RSpec.describe(Take2) do
|
|
151
151
|
raise error
|
152
152
|
end
|
153
153
|
|
154
|
-
|
155
|
-
let(:
|
156
|
-
|
154
|
+
describe 'class method' do
|
155
|
+
let(:retriable_error) { Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil) }
|
157
156
|
before(:each) { @tries = 0 }
|
158
|
-
|
159
|
-
|
160
|
-
expect do
|
161
|
-
object.call_api_with_retry { wrath_the_gods_with error }
|
162
|
-
end.to(raise_error(error.class))
|
157
|
+
it 'responds to the method' do
|
158
|
+
expect(klass).to respond_to(:call_api_with_retry)
|
163
159
|
end
|
164
|
-
|
165
|
-
it 'is not retried' do
|
160
|
+
it 'retries correct number of times' do
|
166
161
|
expect do
|
167
|
-
|
168
|
-
end.to(change { @tries }.from(0).to(1))
|
162
|
+
klass.call_api_with_retry { wrath_the_gods_with retriable_error }
|
163
|
+
end.to(change { @tries }.from(0).to(klass.retriable_configuration[:retries] + 1))
|
169
164
|
rescue
|
170
165
|
nil
|
171
166
|
end
|
172
167
|
end
|
168
|
+
describe 'instance method' do
|
169
|
+
context 'when raised with non retriable error' do
|
170
|
+
let(:error) { StandardError.new('Release the Kraken!!') }
|
173
171
|
|
174
|
-
|
175
|
-
let(:retriable_error) { Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil) }
|
176
|
-
|
177
|
-
before(:each) { @tries = 0 }
|
172
|
+
before(:each) { @tries = 0 }
|
178
173
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
nil
|
185
|
-
end
|
174
|
+
it 're raises the original error' do
|
175
|
+
expect do
|
176
|
+
object.call_api_with_retry { wrath_the_gods_with error }
|
177
|
+
end.to(raise_error(error.class))
|
178
|
+
end
|
186
179
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
.
|
191
|
-
begin
|
192
|
-
object.call_api_with_retry { wrath_the_gods_with retriable_error }
|
180
|
+
it 'is not retried' do
|
181
|
+
expect do
|
182
|
+
object.call_api_with_retry { wrath_the_gods_with error }
|
183
|
+
end.to(change { @tries }.from(0).to(1))
|
193
184
|
rescue
|
194
185
|
nil
|
195
186
|
end
|
196
187
|
end
|
197
188
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
189
|
+
context 'when raised with retriable error' do
|
190
|
+
let(:retriable_error) { Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil) }
|
191
|
+
|
192
|
+
before(:each) { @tries = 0 }
|
193
|
+
|
194
|
+
it 'retries correct number of times' do
|
195
|
+
expect do
|
196
|
+
object.call_api_with_retry { wrath_the_gods_with retriable_error }
|
197
|
+
end.to(change { @tries }.from(0).to(klass.retriable_configuration[:retries] + 1))
|
204
198
|
rescue
|
205
199
|
nil
|
206
200
|
end
|
207
|
-
end
|
208
201
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
202
|
+
it 'calls the retry proc' do
|
203
|
+
expect(klass.retriable_configuration[:retry_proc])
|
204
|
+
.to(receive(:call)
|
205
|
+
.exactly(klass.retriable_configuration[:retries]))
|
206
|
+
begin
|
207
|
+
object.call_api_with_retry { wrath_the_gods_with retriable_error }
|
208
|
+
rescue
|
209
|
+
nil
|
210
|
+
end
|
211
|
+
end
|
217
212
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
213
|
+
it 'calls the retry_condition proc' do
|
214
|
+
expect(klass.retriable_configuration[:retry_condition_proc])
|
215
|
+
.to(receive(:call)
|
216
|
+
.exactly(klass.retriable_configuration[:retries]))
|
217
|
+
begin
|
218
|
+
object.call_api_with_retry { wrath_the_gods_with retriable_error }
|
219
|
+
rescue
|
220
|
+
nil
|
221
|
+
end
|
222
|
+
end
|
224
223
|
|
225
|
-
|
226
|
-
|
227
|
-
|
224
|
+
it 're raises the original error' do
|
225
|
+
expect do
|
226
|
+
object.call_api_with_retry { wrath_the_gods_with retriable_error }
|
227
|
+
end.to(raise_error(retriable_error.class))
|
228
|
+
end
|
229
|
+
end
|
228
230
|
|
229
|
-
|
231
|
+
context 'with custom options' do
|
232
|
+
let(:retriable_error) { Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil) }
|
233
|
+
let(:new_retriable_error) { IOError.new('You shall not PASS!') }
|
230
234
|
|
231
|
-
|
232
|
-
expect do
|
233
|
-
object.call_api_with_retry(retries: 3) { wrath_the_gods_with retriable_error }
|
234
|
-
end.to(change { @tries }.from(0).to(4))
|
235
|
-
rescue
|
236
|
-
nil
|
237
|
-
end
|
235
|
+
before(:each) { @tries = 0 }
|
238
236
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
object.call_api_with_retry(retry_proc: new_proc) { wrath_the_gods_with retriable_error }
|
237
|
+
it 'overwrites the :retries' do
|
238
|
+
expect do
|
239
|
+
object.call_api_with_retry(retries: 3) { wrath_the_gods_with retriable_error }
|
240
|
+
end.to(change { @tries }.from(0).to(4))
|
244
241
|
rescue
|
245
242
|
nil
|
246
243
|
end
|
247
|
-
end
|
248
244
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
245
|
+
it 'overwrites the :retry_proc' do
|
246
|
+
new_proc = proc { 1**1 }
|
247
|
+
expect(new_proc).to(receive(:call).exactly(klass.retriable_configuration[:retries]))
|
248
|
+
begin
|
249
|
+
object.call_api_with_retry(retry_proc: new_proc) { wrath_the_gods_with retriable_error }
|
250
|
+
rescue
|
251
|
+
nil
|
252
|
+
end
|
256
253
|
end
|
257
|
-
end
|
258
254
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
255
|
+
it 'overwrites the :retry_condition_proc' do
|
256
|
+
new_proc = proc { true }
|
257
|
+
expect(new_proc).to(receive(:call).exactly(klass.retriable_configuration[:retries]))
|
258
|
+
begin
|
259
|
+
object.call_api_with_retry(retry_condition_proc: new_proc) { wrath_the_gods_with retriable_error }
|
260
|
+
rescue
|
261
|
+
nil
|
262
|
+
end
|
263
|
+
end
|
267
264
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
265
|
+
it 'overwrites the :retriable' do
|
266
|
+
expect do
|
267
|
+
object.call_api_with_retry(retriable: [new_retriable_error]) { wrath_the_gods_with retriable_error }
|
268
|
+
end.to(change { @tries }.from(0).to(1))
|
269
|
+
rescue
|
270
|
+
nil
|
271
|
+
end
|
275
272
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
273
|
+
it 'raises ArgumentError if there are invalid keys' do
|
274
|
+
expect do
|
275
|
+
object.call_api_with_retry(invalid_key: :nope) { wrath_the_gods_with retriable_error }
|
276
|
+
end.to(raise_error(ArgumentError))
|
277
|
+
end
|
280
278
|
end
|
281
279
|
end
|
282
280
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: take2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Magids
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Retry API calls, methods or blocks of code. Define take2 retry behavior
|
14
14
|
or use defaults and you good to go.
|
@@ -58,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
58
|
version: '0'
|
59
59
|
requirements: []
|
60
60
|
rubyforge_project:
|
61
|
-
rubygems_version: 2.7.
|
61
|
+
rubygems_version: 2.7.9
|
62
62
|
signing_key:
|
63
63
|
specification_version: 4
|
64
64
|
summary: Provides Take2 for your APIs calls
|