take2 0.0.2 → 0.0.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/.circleci/config.yml +53 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +45 -0
- data/README.md +23 -12
- data/lib/take2.rb +17 -11
- data/lib/take2/configuration.rb +22 -6
- data/lib/take2/version.rb +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/take2/configuration_spec.rb +125 -0
- data/spec/take2_spec.rb +130 -26
- data/take2.gemspec +1 -1
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdbb5ecf82b31d399cf75eacacd3a7c8b4cf4aaa
|
4
|
+
data.tar.gz: 3662448022c2ca158c789982b7d51a62ae81c0e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 153630133ce8f3dee9d7f0ef2f0ad2ca57673591ac08435e11b692124aec32cbae50b4d9b2bed42545156168fc3e60f3fa58e61060f5952d08fd5fd74202e582
|
7
|
+
data.tar.gz: 5f73de42c0c6a7381bc6943f5a02d77bc8fc16f893ee59e749699210cd7a4c8f5821d908df8cd830cba92cf59bc254c9b30ab6b2093df86cc4ed9c2da7fd720d
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Ruby CircleCI 2.0 configuration file
|
2
|
+
#
|
3
|
+
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
|
4
|
+
#
|
5
|
+
version: 2
|
6
|
+
jobs:
|
7
|
+
build:
|
8
|
+
docker:
|
9
|
+
# specify the version you desire here
|
10
|
+
- image: circleci/ruby:2.4-node
|
11
|
+
|
12
|
+
# Specify service dependencies here if necessary
|
13
|
+
# CircleCI maintains a library of pre-built images
|
14
|
+
# documented at https://circleci.com/docs/2.0/circleci-images/
|
15
|
+
# - image: circleci/postgres:9.4
|
16
|
+
|
17
|
+
working_directory: ~/take2
|
18
|
+
|
19
|
+
steps:
|
20
|
+
- checkout
|
21
|
+
|
22
|
+
# Download and cache dependencies
|
23
|
+
- restore_cache:
|
24
|
+
keys:
|
25
|
+
- v1-dependencies-{{ checksum "Gemfile.lock" }}
|
26
|
+
# fallback to using the latest cache if no exact match is found
|
27
|
+
- v1-dependencies-
|
28
|
+
|
29
|
+
- run:
|
30
|
+
name: install dependencies
|
31
|
+
command: |
|
32
|
+
bundle install --jobs=4 --retry=3 --path vendor/bundle
|
33
|
+
|
34
|
+
- save_cache:
|
35
|
+
paths:
|
36
|
+
- ./vendor/bundle
|
37
|
+
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
|
38
|
+
|
39
|
+
# run tests!
|
40
|
+
- run:
|
41
|
+
name: run tests
|
42
|
+
command: |
|
43
|
+
mkdir /tmp/test-results
|
44
|
+
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
|
45
|
+
|
46
|
+
bundle exec rspec $TEST_FILES --format doc
|
47
|
+
|
48
|
+
# collect reports
|
49
|
+
- store_test_results:
|
50
|
+
path: /tmp/test-results
|
51
|
+
- store_artifacts:
|
52
|
+
path: /tmp/test-results
|
53
|
+
destination: test-results
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
take2 (0.0.3)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
coderay (1.1.2)
|
10
|
+
diff-lcs (1.3)
|
11
|
+
method_source (0.8.2)
|
12
|
+
pry (0.10.4)
|
13
|
+
coderay (~> 1.1.0)
|
14
|
+
method_source (~> 0.8.1)
|
15
|
+
slop (~> 3.4)
|
16
|
+
pry-nav (0.2.4)
|
17
|
+
pry (>= 0.9.10, < 0.11.0)
|
18
|
+
rake (12.3.1)
|
19
|
+
rspec (3.8.0)
|
20
|
+
rspec-core (~> 3.8.0)
|
21
|
+
rspec-expectations (~> 3.8.0)
|
22
|
+
rspec-mocks (~> 3.8.0)
|
23
|
+
rspec-core (3.8.0)
|
24
|
+
rspec-support (~> 3.8.0)
|
25
|
+
rspec-expectations (3.8.1)
|
26
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
27
|
+
rspec-support (~> 3.8.0)
|
28
|
+
rspec-mocks (3.8.0)
|
29
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
30
|
+
rspec-support (~> 3.8.0)
|
31
|
+
rspec-support (3.8.0)
|
32
|
+
slop (3.6.0)
|
33
|
+
|
34
|
+
PLATFORMS
|
35
|
+
ruby
|
36
|
+
|
37
|
+
DEPENDENCIES
|
38
|
+
pry
|
39
|
+
pry-nav
|
40
|
+
rake
|
41
|
+
rspec (= 3.8.0)
|
42
|
+
take2!
|
43
|
+
|
44
|
+
BUNDLED WITH
|
45
|
+
1.16.4
|
data/README.md
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
## Take2
|
2
|
-
|
2
|
+
[](https://circleci.com/gh/restaurant-cheetah/take2/tree/master)
|
3
|
+

|
4
|
+

|
5
|
+

|
3
6
|
Define rules for retrying behavior.
|
4
7
|
Yield block of code into the public api of the take2.
|
5
8
|
Things getting take two :)
|
6
9
|
|
7
10
|
## Install
|
8
|
-
|
9
|
-
```
|
11
|
+
|
12
|
+
```ruby
|
10
13
|
gem install take2
|
11
14
|
```
|
12
15
|
## Examples
|
13
|
-
|
14
|
-
```
|
16
|
+
|
17
|
+
```ruby
|
15
18
|
class KratosService
|
16
19
|
include Take2
|
17
20
|
|
@@ -39,14 +42,22 @@ class KratosService
|
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
45
|
+
# Pass custom options per method call
|
46
|
+
# The class defaults will not be overwritten
|
47
|
+
def kill_baldur
|
48
|
+
call_api_with_retry(retries: 2, retriable: [IOError], retry_proc: proc {}, retry_condition_proc: proc {}, time_to_sleep: 1.11) do
|
49
|
+
# Some logic that might raise..
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
42
53
|
end
|
43
54
|
|
44
|
-
KratosService.new.call_boy
|
45
|
-
KratosService - Retrying.. 3 of 3 (Release the Kraken...many times!!)
|
46
|
-
KratosService - Retrying.. 2 of 3 (Release the Kraken...many times!!)
|
47
|
-
KratosService - Retrying.. 1 of 3 (Release the Kraken...many times!!)
|
55
|
+
KratosService.new.call_boy
|
56
|
+
#=> KratosService - Retrying.. 3 of 3 (Release the Kraken...many times!!)
|
57
|
+
#=> KratosService - Retrying.. 2 of 3 (Release the Kraken...many times!!)
|
58
|
+
#=> KratosService - Retrying.. 1 of 3 (Release the Kraken...many times!!)
|
48
59
|
# After the retrying is done, original error re-raised
|
49
|
-
Net::HTTPRetriableError: Release the Kraken...many times!!
|
60
|
+
#=> Net::HTTPRetriableError: Release the Kraken...many times!!
|
50
61
|
|
51
62
|
# Not wrapping with method
|
52
63
|
KratosService.new.call_api_with_retry { 1 / 0 }
|
@@ -62,8 +73,8 @@ KratosService.retriable_configuration
|
|
62
73
|
|
63
74
|
## Configurations
|
64
75
|
#### could be implemented as rails initializer
|
65
|
-
|
66
|
-
```
|
76
|
+
|
77
|
+
```ruby
|
67
78
|
# config/initializers/take2.rb
|
68
79
|
|
69
80
|
Take2.configure do |config|
|
data/lib/take2.rb
CHANGED
@@ -23,6 +23,10 @@ module Take2
|
|
23
23
|
@configuration = Configuration.new(options)
|
24
24
|
end
|
25
25
|
|
26
|
+
def self.local_defaults(options)
|
27
|
+
configuration.validate_options(options)
|
28
|
+
end
|
29
|
+
|
26
30
|
def self.configure
|
27
31
|
yield(configuration) if block_given?
|
28
32
|
end
|
@@ -33,7 +37,7 @@ module Take2
|
|
33
37
|
# The raised error could be the defined retriable or it child.
|
34
38
|
#
|
35
39
|
# Example:
|
36
|
-
# class
|
40
|
+
# class PizzaService
|
37
41
|
# include Take2
|
38
42
|
#
|
39
43
|
# number_of_retries 3
|
@@ -51,8 +55,9 @@ module Take2
|
|
51
55
|
# end
|
52
56
|
#
|
53
57
|
# end
|
54
|
-
def call_api_with_retry
|
58
|
+
def call_api_with_retry(options = {})
|
55
59
|
config = self.class.retriable_configuration
|
60
|
+
config.merge! Take2.local_defaults(options) unless options.empty?
|
56
61
|
tries ||= config[:retries]
|
57
62
|
begin
|
58
63
|
yield
|
@@ -75,12 +80,12 @@ module Take2
|
|
75
80
|
# Sets number of retries.
|
76
81
|
#
|
77
82
|
# Example:
|
78
|
-
# class
|
83
|
+
# class PizzaService
|
79
84
|
# include Take2
|
80
85
|
# number_of_retries 3
|
81
86
|
# end
|
82
87
|
# Arguments:
|
83
|
-
# num:
|
88
|
+
# num: integer
|
84
89
|
def number_of_retries(num)
|
85
90
|
raise ArgumentError, 'Must be positive Integer' unless num.is_a?(Integer) && num.positive?
|
86
91
|
self.retries = num
|
@@ -89,13 +94,14 @@ module Take2
|
|
89
94
|
# Sets list of errors on which the block will retry.
|
90
95
|
#
|
91
96
|
# Example:
|
92
|
-
# class
|
97
|
+
# class PizzaService
|
93
98
|
# include Take2
|
94
99
|
# retriable_errors Net::HTTPRetriableError, Errno::ECONNRESET
|
95
100
|
# end
|
96
101
|
# Arguments:
|
97
102
|
# errors: List of retiable errors
|
98
103
|
def retriable_errors(*errors)
|
104
|
+
raise ArgumentError, 'All retriable errors must be StandardError decendants' unless errors.all? { |e| e <= StandardError }
|
99
105
|
self.retriable = errors
|
100
106
|
end
|
101
107
|
|
@@ -103,12 +109,12 @@ module Take2
|
|
103
109
|
# If set, it MUST result to +false+ with number left retries greater that zero in order to retry.
|
104
110
|
#
|
105
111
|
# Example:
|
106
|
-
# class
|
112
|
+
# class PizzaService
|
107
113
|
# include Take2
|
108
114
|
# retriable_condition proc { |error| error.response.status_code < 500 }
|
109
115
|
# end
|
110
116
|
# Arguments:
|
111
|
-
# proc: Proc. The
|
117
|
+
# proc: Proc. The proc called by default with the raised error argument
|
112
118
|
def retriable_condition(proc)
|
113
119
|
raise ArgumentError, 'Must be callable' unless proc.respond_to?(:call)
|
114
120
|
self.retry_condition_proc = proc
|
@@ -117,12 +123,12 @@ module Take2
|
|
117
123
|
# Defines a proc that is called *before* retry attempt.
|
118
124
|
#
|
119
125
|
# Example:
|
120
|
-
# class
|
126
|
+
# class PizzaService
|
121
127
|
# include Take2
|
122
128
|
# on_retry proc { |error, tries| puts "Retrying.. #{tries} of #{self.class.retriable_configuration[:retries]}" }
|
123
129
|
# end
|
124
130
|
# Arguments:
|
125
|
-
# proc: Proc. The
|
131
|
+
# proc: Proc. The proc called by default with the raised error and number of left retries.
|
126
132
|
def on_retry(proc)
|
127
133
|
raise ArgumentError, 'Must be callable' unless proc.respond_to?(:call)
|
128
134
|
self.retry_proc = proc
|
@@ -131,12 +137,12 @@ module Take2
|
|
131
137
|
# Sets number of seconds to sleep before next retry.
|
132
138
|
#
|
133
139
|
# Example:
|
134
|
-
# class
|
140
|
+
# class PizzaService
|
135
141
|
# include Take2
|
136
142
|
# sleep_before_retry 1.5
|
137
143
|
# end
|
138
144
|
# Arguments:
|
139
|
-
# seconds:
|
145
|
+
# seconds: number
|
140
146
|
def sleep_before_retry(seconds)
|
141
147
|
raise ArgumentError, 'Must be positive numer' unless (seconds.is_a?(Integer) || seconds.is_a?(Float)) && seconds.positive?
|
142
148
|
self.time_to_sleep = seconds
|
data/lib/take2/configuration.rb
CHANGED
@@ -17,12 +17,7 @@ module Take2
|
|
17
17
|
@retry_condition_proc = proc { false }
|
18
18
|
@time_to_sleep = 3
|
19
19
|
# Overwriting the defaults
|
20
|
-
options
|
21
|
-
raise ArgumentError, "#{k} is not a valid configuration" unless CONFIG_ATTRS.include?(k)
|
22
|
-
raise ArgumentError, "#{k} must be positive integer" unless v.is_a?(Integer) && v.positive?
|
23
|
-
raise ArgumentError, "#{k} must be positive number" unless (v.is_a?(Integer) || v.is_a?(Float)) && v.positive?
|
24
|
-
instance_variable_set(:"@#{k}", v)
|
25
|
-
end
|
20
|
+
validate_options(options, &setter)
|
26
21
|
end
|
27
22
|
|
28
23
|
def to_hash
|
@@ -35,5 +30,26 @@ module Take2
|
|
35
30
|
self.public_send(value)
|
36
31
|
end
|
37
32
|
|
33
|
+
def validate_options(options, &setter)
|
34
|
+
options.each do |k, v|
|
35
|
+
raise ArgumentError, "#{k} is not a valid configuration" unless CONFIG_ATTRS.include?(k)
|
36
|
+
case k
|
37
|
+
when :retries
|
38
|
+
raise ArgumentError, "#{k} must be positive integer" unless v.is_a?(Integer) && v.positive?
|
39
|
+
when :time_to_sleep
|
40
|
+
raise ArgumentError, "#{k} must be positive number" unless (v.is_a?(Integer) || v.is_a?(Float)) && v >= 0
|
41
|
+
when :retriable
|
42
|
+
raise ArgumentError, "#{k} must be array of retriable errors" unless v.is_a?(Array)
|
43
|
+
when :retry_proc, :retry_condition_proc
|
44
|
+
raise ArgumentError, "#{k} must be Proc" unless v.is_a?(Proc)
|
45
|
+
end
|
46
|
+
setter.call(k, v) if block_given?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def setter
|
51
|
+
proc { |key, value| instance_variable_set(:"@#{key}", value) }
|
52
|
+
end
|
53
|
+
|
38
54
|
end
|
39
55
|
end
|
data/lib/take2/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Take2::Configuration do
|
4
|
+
|
5
|
+
describe 'default configurations' do
|
6
|
+
|
7
|
+
let(:default) { described_class.new }
|
8
|
+
|
9
|
+
it 'has correct default value for retries' do
|
10
|
+
expect(default.retries).to eql 3
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'has correct default retriable errors array' do
|
14
|
+
expect(default.retriable).to eql [
|
15
|
+
Net::HTTPServerError,
|
16
|
+
Net::HTTPServerException,
|
17
|
+
Net::HTTPRetriableError,
|
18
|
+
Errno::ECONNRESET,
|
19
|
+
IOError,
|
20
|
+
].freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'has default proc for retry_proc' do
|
24
|
+
p = proc {}
|
25
|
+
expect(default.retry_proc.call).to eql p.call
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'has default proc for retry_condition_proc' do
|
29
|
+
p = proc {false}
|
30
|
+
expect(default.retry_condition_proc.call).to eql p.call
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'has correct default value for time_to_sleep' do
|
34
|
+
expect(default.time_to_sleep).to eql 3
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'overwriting the default configurations' do
|
40
|
+
|
41
|
+
context 'with valid hash' do
|
42
|
+
|
43
|
+
let!(:new_configs_hash) {
|
44
|
+
{
|
45
|
+
retries: 2,
|
46
|
+
retriable: [Net::HTTPRetriableError],
|
47
|
+
retry_condition_proc: proc { true },
|
48
|
+
retry_proc: proc { 2*2 },
|
49
|
+
time_to_sleep: 0
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
let!(:new_configuration) { described_class.new(new_configs_hash).to_hash }
|
54
|
+
|
55
|
+
[:retries, :retriable, :retry_proc, :retry_condition_proc, :time_to_sleep].each do |key|
|
56
|
+
it "sets the #{key} key" do
|
57
|
+
if new_configs_hash[key].respond_to?(:call)
|
58
|
+
expect(new_configuration[key].call).to eql new_configs_hash[key].call
|
59
|
+
else
|
60
|
+
expect(new_configuration[key]).to eql new_configs_hash[key]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with invalid hash' do
|
68
|
+
|
69
|
+
context 'when retries set to invalid value' do
|
70
|
+
|
71
|
+
it 'raises ArgumentError' do
|
72
|
+
|
73
|
+
expect { described_class.new(retries: -1) }.to raise_error ArgumentError
|
74
|
+
expect { described_class.new(retries: 0) }.to raise_error ArgumentError
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when time_to_sleep set to invalid value' do
|
81
|
+
|
82
|
+
it 'raises ArgumentError' do
|
83
|
+
|
84
|
+
expect { described_class.new(time_to_sleep: -1) }.to raise_error ArgumentError
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'when retriable set to invalid value' do
|
91
|
+
|
92
|
+
it 'raises ArgumentError' do
|
93
|
+
|
94
|
+
expect { described_class.new(retriable: StandardError) }.to raise_error ArgumentError
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when retry_proc set to invalid value' do
|
101
|
+
|
102
|
+
it 'raises ArgumentError' do
|
103
|
+
|
104
|
+
expect { described_class.new(retry_proc: {}) }.to raise_error ArgumentError
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'when retry_condition_proc set to invalid value' do
|
111
|
+
|
112
|
+
it 'raises ArgumentError' do
|
113
|
+
|
114
|
+
expect { described_class.new(retry_condition_proc: {}) }.to raise_error ArgumentError
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
end
|
data/spec/take2_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'take2'
|
3
2
|
|
4
3
|
RSpec.describe Take2 do
|
5
4
|
|
@@ -41,54 +40,115 @@ RSpec.describe Take2 do
|
|
41
40
|
|
42
41
|
end
|
43
42
|
|
44
|
-
describe 'included helpers' do
|
43
|
+
describe 'included class helpers' do
|
45
44
|
|
46
45
|
subject { klass.retriable_configuration }
|
47
46
|
|
48
|
-
describe '
|
47
|
+
describe '.number_of_retries' do
|
48
|
+
|
49
|
+
context 'with valid argument' do
|
50
|
+
|
51
|
+
it 'sets the :retries attribute' do
|
52
|
+
klass.number_of_retries 1
|
53
|
+
expect(subject[:retries]).to eql 1
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'with invalid argument' do
|
59
|
+
|
60
|
+
it 'raises ArgumentError' do
|
61
|
+
expect { klass.number_of_retries 0 }.to raise_error ArgumentError
|
62
|
+
end
|
49
63
|
|
50
|
-
it 'sets the :retries attribute' do
|
51
|
-
klass.number_of_retries 1
|
52
|
-
expect(subject[:retries]).to eql 1
|
53
64
|
end
|
54
65
|
|
55
66
|
end
|
56
67
|
|
57
|
-
describe '
|
68
|
+
describe '.retriable_errors' do
|
69
|
+
|
70
|
+
context 'with valid argument' do
|
71
|
+
|
72
|
+
it 'sets the :retriable_errors attribute' do
|
73
|
+
retriables = IOError
|
74
|
+
klass.retriable_errors retriables
|
75
|
+
expect(subject[:retriable]).to eql [retriables]
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'with invalid argument' do
|
81
|
+
|
82
|
+
it 'raises ArgumentError' do
|
83
|
+
class Klass; end
|
84
|
+
expect { klass.retriable_errors Klass }.to raise_error ArgumentError
|
85
|
+
end
|
58
86
|
|
59
|
-
it 'sets the :retriable_errors attribute' do
|
60
|
-
retriables = IOError
|
61
|
-
klass.retriable_errors retriables
|
62
|
-
expect(subject[:retriable]).to eql [retriables]
|
63
87
|
end
|
64
88
|
|
65
89
|
end
|
66
90
|
|
67
|
-
describe '
|
91
|
+
describe '.retriable_condition' do
|
92
|
+
|
93
|
+
context 'with valid argument' do
|
94
|
+
|
95
|
+
it 'sets the :retriable_condition attribute' do
|
96
|
+
retriable_proc = proc { 'Ho-Ho-Ho' }
|
97
|
+
klass.retriable_condition retriable_proc
|
98
|
+
expect(subject[:retry_condition_proc].call).to eql retriable_proc.call
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'with invalid argument' do
|
104
|
+
|
105
|
+
it 'raises ArgumentError' do
|
106
|
+
expect { klass.retriable_condition Class.new }.to raise_error ArgumentError
|
107
|
+
end
|
68
108
|
|
69
|
-
it 'sets the :retriable_condition attribute' do
|
70
|
-
retriable_proc = proc { 'Ho-Ho-Ho' }
|
71
|
-
klass.retriable_condition retriable_proc
|
72
|
-
expect(subject[:retry_condition_proc].call).to eql retriable_proc.call
|
73
109
|
end
|
74
110
|
|
75
111
|
end
|
76
112
|
|
77
|
-
describe '
|
113
|
+
describe '.on_retry' do
|
114
|
+
|
115
|
+
context 'with valid argument' do
|
116
|
+
|
117
|
+
it 'sets the :on_retry attribute' do
|
118
|
+
retry_proc = proc { |el| el }
|
119
|
+
klass.on_retry retry_proc
|
120
|
+
expect(subject[:retry_proc].call).to eql retry_proc.call
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'with invalid argument' do
|
126
|
+
|
127
|
+
it 'raises ArgumentError' do
|
128
|
+
expect { klass.on_retry Class.new }.to raise_error ArgumentError
|
129
|
+
end
|
78
130
|
|
79
|
-
it 'sets the :on_retry attribute' do
|
80
|
-
retry_proc = proc { |el| el }
|
81
|
-
klass.on_retry retry_proc
|
82
|
-
expect(subject[:retry_proc].call).to eql retry_proc.call
|
83
131
|
end
|
84
132
|
|
85
133
|
end
|
86
134
|
|
87
|
-
describe '
|
135
|
+
describe '.sleep_before_retry' do
|
136
|
+
|
137
|
+
context 'with valid argument' do
|
138
|
+
|
139
|
+
it 'sets the :sleep_before_retry attribute' do
|
140
|
+
klass.sleep_before_retry 3.5
|
141
|
+
expect(subject[:time_to_sleep]).to eql 3.5
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'with invalid argument' do
|
147
|
+
|
148
|
+
it 'raises ArgumentError' do
|
149
|
+
expect { klass.sleep_before_retry -1 }.to raise_error ArgumentError
|
150
|
+
end
|
88
151
|
|
89
|
-
it 'sets the :sleep_before_retry attribute' do
|
90
|
-
klass.sleep_before_retry 3.5
|
91
|
-
expect(subject[:time_to_sleep]).to eql 3.5
|
92
152
|
end
|
93
153
|
|
94
154
|
end
|
@@ -140,7 +200,7 @@ RSpec.describe Take2 do
|
|
140
200
|
it 'retries correct number of times' do
|
141
201
|
expect do
|
142
202
|
object.call_api_with_retry { wrath_the_gods_with retriable_error } rescue nil
|
143
|
-
end.to change{@tries}.from(0).to(klass.retriable_configuration[:retries] + 1)
|
203
|
+
end.to change {@tries}.from(0).to(klass.retriable_configuration[:retries] + 1)
|
144
204
|
end
|
145
205
|
|
146
206
|
it 'calls the retry proc' do
|
@@ -171,6 +231,50 @@ RSpec.describe Take2 do
|
|
171
231
|
|
172
232
|
end
|
173
233
|
|
234
|
+
context 'with custom options' do
|
235
|
+
|
236
|
+
let(:retriable_error) { Net::HTTPRetriableError.new 'Release the Kraken...many times!!', nil }
|
237
|
+
let(:new_retriable_error) { IOError.new 'You shall not PASS!' }
|
238
|
+
|
239
|
+
before(:each) { @tries = 0 }
|
240
|
+
|
241
|
+
it 'overwrites the :retries' do
|
242
|
+
expect do
|
243
|
+
object.call_api_with_retry(retries: 3) { wrath_the_gods_with retriable_error } rescue nil
|
244
|
+
end.to change { @tries }.from(0).to(4)
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'overwrites the :retry_proc' do
|
248
|
+
new_proc = proc { 1**1 }
|
249
|
+
expect(new_proc).to receive(:call).exactly(klass.retriable_configuration[:retries])
|
250
|
+
object.call_api_with_retry(retry_proc: new_proc) { wrath_the_gods_with retriable_error } rescue nil
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'overwrites the :retry_condition_proc' do
|
254
|
+
new_proc = proc { true }
|
255
|
+
expect(new_proc).to receive(:call).exactly(klass.retriable_configuration[:retries])
|
256
|
+
object.call_api_with_retry(retry_condition_proc: new_proc) { wrath_the_gods_with retriable_error } rescue nil
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'overwrites the :time_to_sleep' do
|
260
|
+
allow_any_instance_of(Object).to receive(:sleep).with(1.66)
|
261
|
+
object.call_api_with_retry(time_to_sleep: 1.66) { wrath_the_gods_with retriable_error } rescue nil
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'overwrites the :retriable' do
|
265
|
+
expect do
|
266
|
+
object.call_api_with_retry(retriable: [new_retriable_error]) { wrath_the_gods_with retriable_error } rescue nil
|
267
|
+
end.to change { @tries }.from(0).to(1)
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'raises ArgumentError if there are invalid keys' do
|
271
|
+
expect do
|
272
|
+
object.call_api_with_retry(invalid_key: :nope) { wrath_the_gods_with retriable_error }
|
273
|
+
end.to raise_error ArgumentError
|
274
|
+
end
|
275
|
+
|
276
|
+
end
|
277
|
+
|
174
278
|
end
|
175
279
|
|
176
280
|
end
|
data/take2.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.email = ["evnomadx@gmail.com"]
|
10
10
|
s.homepage = "https://github.com/restaurant-cheetah/take2"
|
11
11
|
s.summary = "Provides Take2 for your APIs calls"
|
12
|
-
s.description = "
|
12
|
+
s.description = "Retry API calls, methods or blocks of code. Define take2 retry behavior or use defaults and you good to go."
|
13
13
|
s.post_install_message = "Getting Take2 is dead easy!"
|
14
14
|
|
15
15
|
all_files = `git ls-files`.split("\n")
|
metadata
CHANGED
@@ -1,28 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: take2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Magids
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-09-
|
11
|
+
date: 2018-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
14
|
-
or
|
13
|
+
description: Retry API calls, methods or blocks of code. Define take2 retry behavior
|
14
|
+
or use defaults and you good to go.
|
15
15
|
email:
|
16
16
|
- evnomadx@gmail.com
|
17
17
|
executables: []
|
18
18
|
extensions: []
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
|
+
- ".circleci/config.yml"
|
21
22
|
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
22
23
|
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
23
24
|
- ".gitignore"
|
24
25
|
- CHANGELOG.md
|
25
26
|
- Gemfile
|
27
|
+
- Gemfile.lock
|
26
28
|
- LICENSE
|
27
29
|
- README.md
|
28
30
|
- Rakefile
|
@@ -30,6 +32,7 @@ files:
|
|
30
32
|
- lib/take2/configuration.rb
|
31
33
|
- lib/take2/version.rb
|
32
34
|
- spec/spec_helper.rb
|
35
|
+
- spec/take2/configuration_spec.rb
|
33
36
|
- spec/take2_spec.rb
|
34
37
|
- take2.gemspec
|
35
38
|
homepage: https://github.com/restaurant-cheetah/take2
|
@@ -58,4 +61,5 @@ specification_version: 4
|
|
58
61
|
summary: Provides Take2 for your APIs calls
|
59
62
|
test_files:
|
60
63
|
- spec/spec_helper.rb
|
64
|
+
- spec/take2/configuration_spec.rb
|
61
65
|
- spec/take2_spec.rb
|