take2 0.1.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ad4dbf81975a5cc73474e2423a154804f890402129dc86bd3a84f33d3bb7014e
4
- data.tar.gz: 5db4c75eb7b03d975a6f4fcd36f92995107737e487cfa9e0ebc0b4c35683dbe9
3
+ metadata.gz: 1cb318b781932656dc817f9129c5621b55b99dc377968ffb0931f6ba3c044ab5
4
+ data.tar.gz: 28e00524af5f1ba059445018d47bffb0216b7517949d4ad8ed61da951db3be6f
5
5
  SHA512:
6
- metadata.gz: 318ddd7bc40de226b01e17d7f54106f34e41b63317ec14bd146c9df2a2cca003341c34c93929771bd13caf92d82759f9abb9d92e1d151df758877bf34eff5e01
7
- data.tar.gz: c50474f5331470bf1ac546507a6fd13c36f70f97fe0a7e98554c73c7cc94ab18861566d1998190fa517ea8ab7d3418244c16de1a014486522fdd7f4667f68890
6
+ metadata.gz: b9c3335fd97336deb6e7f1b0e82cf040779dbec24bb81b20b1b8bff5422e3c3612abdc49eb5c8b09e609d3e8a17941c64fdb5c4dfd417d7ebb7cec4a3a9d4ca4
7
+ data.tar.gz: 03aea65024971befd1c0e1db2e8d2a1dae3d9bf8ad82f87017d8c75b0461246cc5e366ef33e90dae1f4201b97b673e1acdbec8212ead4d64428104e3b6d72cf4
data/.gitignore CHANGED
@@ -48,3 +48,6 @@ build-iPhoneSimulator/
48
48
 
49
49
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
50
  .rvmrc
51
+ .idea
52
+ .ruby-gemset
53
+ .ruby-version
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- take2 (0.1.1)
4
+ take2 (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -22,7 +22,7 @@ GEM
22
22
  pry-nav (0.2.4)
23
23
  pry (>= 0.9.10, < 0.11.0)
24
24
  rainbow (3.0.0)
25
- rake (12.3.1)
25
+ rake (13.0.1)
26
26
  rspec (3.8.0)
27
27
  rspec-core (~> 3.8.0)
28
28
  rspec-expectations (~> 3.8.0)
@@ -60,4 +60,4 @@ DEPENDENCIES
60
60
  take2!
61
61
 
62
62
  BUNDLED WITH
63
- 1.16.6
63
+ 1.17.3
data/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
  ![Gem](https://img.shields.io/gem/dt/take2.svg)
4
4
  ![GitHub last commit](https://img.shields.io/github/last-commit/restaurant-cheetah/take2.svg)
5
5
  ![Gem](https://img.shields.io/gem/v/take2.svg)
6
- Define rules for retrying behavior.
7
- Yield block of code into the public api of the take2.
8
- Things getting take two :)
6
+ 1. Define rules for retrying behavior.
7
+ 2. Yield block of code into the with_retry method.
8
+ 3. Things getting take two :)
9
9
 
10
10
  ## Install
11
11
 
@@ -15,64 +15,57 @@ gem install take2
15
15
  ## Examples
16
16
 
17
17
  ```ruby
18
- class KratosService
18
+ class Service
19
19
  include Take2
20
20
 
21
-
22
21
  number_of_retries 3
23
-
22
+
24
23
  # Could be configured globally or on class level.
25
- retriable_errors Net::HTTPRetriableError, Net::HTTPServerException
24
+ retriable_errors Net::HTTPRetriableError, Errno::ECONNRESET
26
25
 
27
26
  # Retry unless the response status is 5xx. The implementation is dependent of the http lib in use.
28
27
  retriable_condition proc { |error| error.response.code < 500 }
29
28
 
30
29
  # Defines callable code to run before next retry. Could be an out put to some logger.
31
- on_retry proc { |error, tries| puts "#{self.name} - Retrying.. #{tries} of #{self.retriable_configuration[:retries]} (#{error})" }
32
-
33
- # The available strategies are:
30
+ on_retry proc { |error, tries| puts "#{name} - Retrying.. #{tries} of #{retriable_configuration[:retries]} (#{error})" }
31
+
32
+ # The available strategies are:
34
33
  # type :constant, start: 2 => [2, 2, 2, 2 ... ]
35
34
  # type :linear, start: 3, factor: 2 => [3, 6, 12, 24 ... ]
36
35
  # type :fibonacci, start: 2 => [2, 3, 5, 8, 13 ... ]
37
- # type :exponential, start: 3 => [3, 7, 12, 28, 47 ... ]
36
+ # type :exponential, start: 3 => [3, 7, 12, 28, 47 ... ]
38
37
  backoff_strategy type: :fibonacci, start: 3
39
38
 
40
- def call_boy
41
- call_api_with_retry do
42
- # Some logic that might raise..
43
- # If it will raise retriable, magic happens.
44
- # If not the original error re raised
39
+ class << self
40
+ def call
41
+ with_retry do
42
+ # Some logic that might raise..
43
+ # If it will raise retriable, magic happens.
44
+ # If not the original error re raised
45
45
 
46
- raise Net::HTTPRetriableError.new 'Release the Kraken...many times!!', nil
46
+ raise Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil)
47
+ end
47
48
  end
48
- end
49
49
 
50
- # Pass custom options per method call
51
- # The class defaults will not be overwritten
52
- def kill_baldur
53
- call_api_with_retry(retries: 2, retriable: [IOError], retry_proc: proc {}, retry_condition_proc: proc {}) do
54
- # Some logic that might raise..
50
+ # Pass custom options per method call
51
+ # The class defaults will not be overwritten
52
+ def read(file)
53
+ with_retry(retries: 2, retriable: [IOError], retry_proc: proc {}, retry_condition_proc: proc {}) do
54
+ # Some logic that might raise..
55
+ end
55
56
  end
56
57
  end
57
-
58
58
  end
59
59
 
60
- KratosService.new.call_boy
60
+ Service.call
61
61
  #=> KratosService - Retrying.. 3 of 3 (Release the Kraken...many times!!)
62
62
  #=> KratosService - Retrying.. 2 of 3 (Release the Kraken...many times!!)
63
63
  #=> KratosService - Retrying.. 1 of 3 (Release the Kraken...many times!!)
64
64
  # After the retrying is done, original error re-raised
65
65
  #=> Net::HTTPRetriableError: Release the Kraken...many times!!
66
66
 
67
- # Not wrapping with method
68
- KratosService.new.call_api_with_retry { 1 / 0 }
69
-
70
- # Or..
71
- Class.new { include Take2 }.new.call_api_with_retry { 1 / 0 }
72
-
73
-
74
67
  # Current configuration hash
75
- KratosService.retriable_configuration
68
+ Service.retriable_configuration
76
69
 
77
70
  ```
78
71
 
@@ -84,15 +77,13 @@ KratosService.retriable_configuration
84
77
 
85
78
  Take2.configure do |config|
86
79
  config.retries = 3
87
- config.retriable = [
88
- Net::HTTPServerException,
80
+ config.retriable = [
89
81
  Net::HTTPRetriableError,
90
82
  Errno::ECONNRESET,
91
83
  IOError
92
84
  ].freeze
93
- config.retry_condition_proc = proc {false}
94
- config.time_to_sleep = nil
95
- config.retry_proc = proc {Rails.logger.info "Retry message"}
85
+ config.retry_condition_proc = proc { false }
86
+ config.retry_proc = proc { Rails.logger.info "Retry message" }
96
87
  config.backoff_intervals = Take2::Backoff.new(:linear, 1).intervals
97
88
  end
98
89
  ```
@@ -23,11 +23,14 @@ module Take2
23
23
  end
24
24
 
25
25
  def local_defaults(options)
26
- configuration.validate_options(options)
26
+ configuration.validate!(options)
27
27
  end
28
28
 
29
29
  def configure
30
- yield(config) if block_given?
30
+ if block_given?
31
+ yield(config)
32
+ config.validate!(config.to_hash)
33
+ end
31
34
  end
32
35
  end
33
36
 
@@ -48,7 +51,7 @@ module Take2
48
51
  # backoff_strategy type: :exponential, start: 3
49
52
  #
50
53
  # def give_me_food
51
- # call_api_with_retry do
54
+ # with_retry do
52
55
  # # Some logic that might raise..
53
56
  # # If it will raise retriable, magic happens.
54
57
  # # If not the original error re raised
@@ -107,9 +110,9 @@ module Take2
107
110
  # retriable_errors Net::HTTPRetriableError, Errno::ECONNRESET
108
111
  # end
109
112
  # Arguments:
110
- # errors: List of retiable errors
113
+ # errors: List of retriable errors
111
114
  def retriable_errors(*errors)
112
- message = 'All retriable errors must be StandardError decendants'
115
+ message = 'All retriable errors must be StandardError descendants'
113
116
  raise ArgumentError, message unless errors.all? { |e| e <= StandardError }
114
117
  self.retriable = errors
115
118
  end
@@ -143,15 +146,6 @@ module Take2
143
146
  self.retry_proc = proc
144
147
  end
145
148
 
146
- def sleep_before_retry(seconds)
147
- unless (seconds.is_a?(Integer) || seconds.is_a?(Float)) && seconds.positive?
148
- raise ArgumentError, 'Must be positive numer'
149
- end
150
- puts "DEPRECATION MESSAGE - The sleep_before_retry method is softly deprecated in favor of backoff_stategy \r
151
- where the time to sleep is a starting point on the backoff intervals. Please implement it instead."
152
- self.time_to_sleep = seconds
153
- end
154
-
155
149
  # Sets the backoff strategy
156
150
  #
157
151
  # Example:
@@ -179,9 +173,8 @@ module Take2
179
173
  attr_accessor(*Take2::Configuration::CONFIG_ATTRS)
180
174
 
181
175
  def set_defaults
182
- config = Take2.configuration.to_hash
183
- Take2::Configuration::CONFIG_ATTRS.each do |attr|
184
- instance_variable_set("@#{attr}", config[attr])
176
+ Take2.config.to_hash.each do |k, v|
177
+ instance_variable_set("@#{k}", v)
185
178
  end
186
179
  end
187
180
 
@@ -191,11 +184,7 @@ module Take2
191
184
  end
192
185
 
193
186
  def rest(config, tries)
194
- seconds = if config[:time_to_sleep].to_f > 0
195
- config[:time_to_sleep].to_f
196
- else
197
- next_interval(config[:backoff_intervals], config[:retries], tries)
198
- end
187
+ seconds = next_interval(config[:backoff_intervals], config[:retries], tries)
199
188
  sleep(seconds)
200
189
  end
201
190
 
@@ -8,8 +8,6 @@ module Take2
8
8
  :retriable,
9
9
  :retry_proc,
10
10
  :retry_condition_proc,
11
- :time_to_sleep,
12
- :backoff_setup,
13
11
  :backoff_intervals].freeze
14
12
 
15
13
  attr_accessor(*CONFIG_ATTRS)
@@ -17,19 +15,12 @@ module Take2
17
15
  def initialize(options = {})
18
16
  # Defaults
19
17
  @retries = 3
20
- @retriable = [
21
- Net::HTTPServerException,
22
- Net::HTTPRetriableError,
23
- Errno::ECONNRESET,
24
- IOError,
25
- ].freeze
18
+ @retriable = []
26
19
  @retry_proc = proc {}
27
20
  @retry_condition_proc = proc { false }
28
- @time_to_sleep = 0 # TODO: Soft deprecate time to sleep
29
- @backoff_setup = { type: :constant, start: 3 }
30
- @backoff_intervals = Backoff.new(*@backoff_setup.values).intervals
31
- # Overwriting the defaults
32
- validate_options(options, &setter)
21
+ @backoff_intervals = Backoff.new(:constant, 3).intervals
22
+
23
+ merge_options!(options)
33
24
  end
34
25
 
35
26
  def to_hash
@@ -42,38 +33,28 @@ module Take2
42
33
  public_send(value)
43
34
  end
44
35
 
45
- def validate_options(options)
36
+ def merge_options!(options = {})
37
+ validate!(options).each do |key, value|
38
+ public_send("#{key}=", value)
39
+ end
40
+ self
41
+ end
42
+
43
+ def validate!(options)
46
44
  options.each do |k, v|
47
45
  raise ArgumentError, "#{k} is not a valid configuration" unless CONFIG_ATTRS.include?(k)
48
46
  case k
49
47
  when :retries
50
48
  raise ArgumentError, "#{k} must be positive integer" unless v.is_a?(Integer) && v.positive?
51
- when :time_to_sleep
52
- raise ArgumentError, "#{k} must be positive number" unless (v.is_a?(Integer) || v.is_a?(Float)) && v >= 0
53
49
  when :retriable
54
50
  raise ArgumentError, "#{k} must be array of retriable errors" unless v.is_a?(Array)
51
+ when :backoff_intervals
52
+ raise ArgumentError, "#{k} must be array of retriable errors" unless v.is_a?(Array)
53
+ raise ArgumentError, "#{k} size must be greater or equal to number of retries" unless v.size >= retries
55
54
  when :retry_proc, :retry_condition_proc
56
55
  raise ArgumentError, "#{k} must be Proc" unless v.is_a?(Proc)
57
- when :backoff_setup
58
- available_types = [:constant, :linear, :fibonacci, :exponential]
59
- raise ArgumentError, 'Incorrect backoff type' unless available_types.include?(v[:type])
60
56
  end
61
- yield(k, v) if block_given?
62
57
  end
63
58
  end
64
-
65
- def setter
66
- ->(key, value) {
67
- if key == :backoff_setup
68
- assign_backoff_intervals(value)
69
- else
70
- public_send("#{key}=", value)
71
- end
72
- }
73
- end
74
-
75
- def assign_backoff_intervals(backoff_setup)
76
- @backoff_intervals = Backoff.new(backoff_setup[:type], backoff_setup[:start]).intervals
77
- end
78
59
  end
79
60
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Take2
4
- VERSION = "0.1.1"
4
+ VERSION = "1.0.0"
5
5
  end
@@ -11,12 +11,7 @@ RSpec.describe(Take2::Configuration) do
11
11
  end
12
12
 
13
13
  it 'has correct default retriable errors array' do
14
- expect(default.retriable).to(eql([
15
- Net::HTTPServerException,
16
- Net::HTTPRetriableError,
17
- Errno::ECONNRESET,
18
- IOError,
19
- ].freeze))
14
+ expect(default.retriable).to(eql([]))
20
15
  end
21
16
 
22
17
  it 'has default proc for retry_proc' do
@@ -29,10 +24,6 @@ RSpec.describe(Take2::Configuration) do
29
24
  expect(default.retry_condition_proc.call).to(eql(p.call))
30
25
  end
31
26
 
32
- it 'has correct default value for time_to_sleep' do
33
- expect(default.time_to_sleep).to(eql(0))
34
- end
35
-
36
27
  it 'has correct default value for backoff_intervals' do
37
28
  expect(default.backoff_intervals).to eql Array.new(10, 3)
38
29
  end
@@ -46,14 +37,13 @@ RSpec.describe(Take2::Configuration) do
46
37
  retriable: [Net::HTTPRetriableError],
47
38
  retry_condition_proc: proc { true },
48
39
  retry_proc: proc { 2 * 2 },
49
- time_to_sleep: 0,
50
- backoff_setup: { type: :linear, start: 3 }
40
+ backoff_intervals: [1, 2, 3, 4, 5]
51
41
  }
52
42
  end
53
43
 
54
44
  let!(:new_configuration) { described_class.new(new_configs_hash).to_hash }
55
45
 
56
- [:retries, :retriable, :retry_proc, :retry_condition_proc, :time_to_sleep].each do |key|
46
+ [:retries, :retriable, :retry_proc, :retry_condition_proc, :backoff_intervals].each do |key|
57
47
  it "sets the #{key} key" do
58
48
  if new_configs_hash[key].respond_to?(:call)
59
49
  expect(new_configuration[key].call).to(eql(new_configs_hash[key].call))
@@ -62,14 +52,6 @@ RSpec.describe(Take2::Configuration) do
62
52
  end
63
53
  end
64
54
  end
65
-
66
- it 'sets the backoff_intervals correctly' do
67
- expect(new_configuration[:backoff_intervals])
68
- .to eql(Take2::Backoff.new(
69
- new_configs_hash[:backoff_setup][:type],
70
- new_configs_hash[:backoff_setup][:start]
71
- ).intervals)
72
- end
73
55
  end
74
56
 
75
57
  context 'with invalid hash' do
@@ -80,12 +62,6 @@ RSpec.describe(Take2::Configuration) do
80
62
  end
81
63
  end
82
64
 
83
- context 'when time_to_sleep set to invalid value' do
84
- it 'raises ArgumentError' do
85
- expect { described_class.new(time_to_sleep: -1) }.to(raise_error(ArgumentError))
86
- end
87
- end
88
-
89
65
  context 'when retriable set to invalid value' do
90
66
  it 'raises ArgumentError' do
91
67
  expect { described_class.new(retriable: StandardError) }.to(raise_error(ArgumentError))
@@ -104,9 +80,15 @@ RSpec.describe(Take2::Configuration) do
104
80
  end
105
81
  end
106
82
 
107
- context 'when backoff_setup has incorrect type' do
83
+ context 'when backoff_intervals has incorrect type' do
84
+ it 'raises ArgumentError' do
85
+ expect { described_class.new(backoff_intervals: 1) }.to(raise_error(ArgumentError))
86
+ end
87
+ end
88
+
89
+ context 'when backoff_intervals size smaller then number of retries' do
108
90
  it 'raises ArgumentError' do
109
- expect { described_class.new(backoff_setup: { type: :log }) }.to(raise_error(ArgumentError))
91
+ expect { described_class.new(backoff_intervals: [1]) }.to(raise_error(ArgumentError))
110
92
  end
111
93
  end
112
94
  end
@@ -6,10 +6,9 @@ RSpec.describe(Take2) do
6
6
  let!(:config) do
7
7
  Take2.configure do |c|
8
8
  c.retries = 1
9
- c.retriable = [Net::HTTPServerException, Net::HTTPRetriableError].freeze
9
+ c.retriable = [Errno::ECONNRESET, Net::HTTPRetriableError].freeze
10
10
  c.retry_condition_proc = proc { false }
11
11
  c.retry_proc = proc {}
12
- c.time_to_sleep = 0
13
12
  c.backoff_intervals = Take2::Backoff.new(:linear, 1).intervals
14
13
  end
15
14
  end
@@ -35,10 +34,6 @@ RSpec.describe(Take2) do
35
34
  expect(subject[:retry_proc].call).to(eql(described_class.configuration[:retry_proc].call))
36
35
  end
37
36
 
38
- it 'has a default value for :time_to_sleep' do
39
- expect(subject[:time_to_sleep]).to(eql(described_class.configuration[:time_to_sleep]))
40
- end
41
-
42
37
  it 'has a default value for :backoff_intervals' do
43
38
  expect(subject[:backoff_intervals]).to eql((1..10).to_a)
44
39
  end
@@ -111,21 +106,6 @@ RSpec.describe(Take2) do
111
106
  end
112
107
  end
113
108
 
114
- describe '.sleep_before_retry' do
115
- context 'with valid argument' do
116
- it 'sets the :sleep_before_retry attribute' do
117
- klass.sleep_before_retry(3.5)
118
- expect(subject[:time_to_sleep]).to(eql(3.5))
119
- end
120
- end
121
-
122
- context 'with invalid argument' do
123
- it 'raises ArgumentError' do
124
- expect { klass.sleep_before_retry(-1) }.to(raise_error(ArgumentError))
125
- end
126
- end
127
- end
128
-
129
109
  describe '.backoff_setup' do
130
110
  context 'with valid arguments' do
131
111
  it 'sets the backoff_intervals' do
@@ -154,12 +134,14 @@ RSpec.describe(Take2) do
154
134
  describe 'class method' do
155
135
  let(:retriable_error) { Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil) }
156
136
  before(:each) { @tries = 0 }
137
+
157
138
  it 'responds to the method' do
158
139
  expect(klass).to respond_to(:call_api_with_retry)
159
140
  expect(klass).to respond_to(:with_retry)
160
141
  expect(klass.method(:with_retry).original_name).to eq(klass.method(:call_api_with_retry).original_name)
161
142
  expect(klass.method(:with_retry).source_location).to eq(klass.method(:call_api_with_retry).source_location)
162
143
  end
144
+
163
145
  it 'retries correct number of times' do
164
146
  expect do
165
147
  klass.call_api_with_retry { wrath_the_gods_with retriable_error }
@@ -168,6 +150,7 @@ RSpec.describe(Take2) do
168
150
  nil
169
151
  end
170
152
  end
153
+
171
154
  describe 'instance method' do
172
155
  it 'responds to the method' do
173
156
  expect(object).to respond_to(:call_api_with_retry)
@@ -175,6 +158,7 @@ RSpec.describe(Take2) do
175
158
  expect(object.method(:with_retry).original_name).to eq(object.method(:call_api_with_retry).original_name)
176
159
  expect(object.method(:with_retry).source_location).to eq(object.method(:call_api_with_retry).source_location)
177
160
  end
161
+
178
162
  context 'when raised with non retriable error' do
179
163
  let(:error) { StandardError.new('Release the Kraken!!') }
180
164
 
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.email = ["evnomadx@gmail.com"]
12
12
  s.homepage = "https://github.com/restaurant-cheetah/take2"
13
13
  s.summary = "Provides Take2 for your APIs calls"
14
- s.description = "Retry API calls, methods or blocks of code. Define take2 retry behavior or use defaults and you good to go."
14
+ s.description = "Retry failed API calls, methods or blocks of code. Define take2 retry behavior on a class or method level and you good to go."
15
15
  s.post_install_message = "Getting Take2 is dead easy!"
16
16
 
17
17
  all_files = %x(git ls-files).split("\n")
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: take2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.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-08-21 00:00:00.000000000 Z
11
+ date: 2020-08-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Retry API calls, methods or blocks of code. Define take2 retry behavior
14
- or use defaults and you good to go.
13
+ description: Retry failed API calls, methods or blocks of code. Define take2 retry
14
+ behavior on a class or method level and you good to go.
15
15
  email:
16
16
  - evnomadx@gmail.com
17
17
  executables: []
@@ -57,8 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
57
  - !ruby/object:Gem::Version
58
58
  version: '0'
59
59
  requirements: []
60
- rubyforge_project:
61
- rubygems_version: 2.7.9
60
+ rubygems_version: 3.0.8
62
61
  signing_key:
63
62
  specification_version: 4
64
63
  summary: Provides Take2 for your APIs calls