easy_retry 1.0.7 → 1.0.8.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 830b86bc6808d551a48e8cf1c12618ad9de85798f1528bf99c7cab98a609353a
4
- data.tar.gz: 7c633deca8936603e22f2673cf5dde56c5b934565ed04cdf50452e69c2b2688f
3
+ metadata.gz: 1dd6fbeba47923f12a6c9ec7fce4f67f7369a612790756b1ba2459492282199f
4
+ data.tar.gz: aecd43808908c13e591ae1b7a248eebe864d2195959f27a39b87e9142075a548
5
5
  SHA512:
6
- metadata.gz: 57b5e797ced529a355a651b81860377394ce12231435857ebc036b34022b84db369c7338a2a390bdcc8eb2de5fad017f749038c651c034ee5069cbf96bbe507a
7
- data.tar.gz: 4ac048a61a96bdee00821f5f9d3109320a519610feb0ba4f060c5358bbd36090d71db1d8c3bbc39a87b23444e7ec3a2af5aac13d77e5cb06d1efe225f9beadda
6
+ metadata.gz: 172f6145588b03f8240d809e58e9fe390f093f0f81cadb589fa5d50cbf56c0ab2e076446425fb4cf552790eda81338baf796da8b7879e7b71bb7c84e014500b8
7
+ data.tar.gz: b150f796f511124b0b05abfbc7fa7a6d4c621703d0b1fe6acbc7e141130b9dd44d5215a5210ad438ed6b419b0cb47a88a0ba59128a697c39852a27aeb6c0de5c
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## [Released]
4
4
 
5
+ ## [1.0.8] - 2022-12-13
6
+
7
+ - Add delay configuration
8
+
5
9
  ## [1.0.7] - 2022-11-23
6
10
 
7
11
  - Log the error class rather than `Error`.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- easy_retry (1.0.7)
4
+ easy_retry (1.0.8)
5
5
  logger (~> 1.5.1)
6
6
 
7
7
  GEM
@@ -11,11 +11,11 @@ GEM
11
11
  coderay (1.1.3)
12
12
  diff-lcs (1.5.0)
13
13
  docile (1.4.0)
14
- json (2.6.2)
15
- logger (1.5.1)
14
+ json (2.6.3)
15
+ logger (1.5.2)
16
16
  method_source (1.0.0)
17
17
  parallel (1.22.1)
18
- parser (3.1.2.1)
18
+ parser (3.1.3.0)
19
19
  ast (~> 2.4.1)
20
20
  pry (0.14.1)
21
21
  coderay (~> 1.1)
@@ -33,11 +33,11 @@ GEM
33
33
  rspec-expectations (3.12.0)
34
34
  diff-lcs (>= 1.2.0, < 2.0)
35
35
  rspec-support (~> 3.12.0)
36
- rspec-mocks (3.12.0)
36
+ rspec-mocks (3.12.1)
37
37
  diff-lcs (>= 1.2.0, < 2.0)
38
38
  rspec-support (~> 3.12.0)
39
39
  rspec-support (3.12.0)
40
- rubocop (1.39.0)
40
+ rubocop (1.40.0)
41
41
  json (~> 2.3)
42
42
  parallel (~> 1.10)
43
43
  parser (>= 3.1.2.1)
@@ -47,7 +47,7 @@ GEM
47
47
  rubocop-ast (>= 1.23.0, < 2.0)
48
48
  ruby-progressbar (~> 1.7)
49
49
  unicode-display_width (>= 1.4.0, < 3.0)
50
- rubocop-ast (1.23.0)
50
+ rubocop-ast (1.24.0)
51
51
  parser (>= 3.1.1.0)
52
52
  ruby-progressbar (1.11.0)
53
53
  simplecov (0.21.2)
data/README.md CHANGED
@@ -28,24 +28,24 @@ Or install it yourself as:
28
28
 
29
29
  If you're not using Bundler, you'll need to require the gem in your code:
30
30
  ```rb
31
- require 'easy_retry'
31
+ require 'easy_retry'
32
32
  ```
33
33
 
34
34
  ### Basic Example
35
35
 
36
36
  ```rb
37
- 4.tries do |try|
38
- raise 'Something went wrong' if try < 4
39
- puts "Success!"
40
- end
37
+ 4.tries do |try|
38
+ raise 'Something went wrong' if try < 4
39
+ puts "Success!"
40
+ end
41
41
  ```
42
42
 
43
43
  The code above will produce the following output:
44
44
 
45
45
  ```
46
- Error: Something went wrong (1/4)
47
- Error: Something went wrong (2/4)
48
- Error: Something went wrong (3/4)
46
+ RuntimeError: Something went wrong (1/4)
47
+ RuntimeError: Something went wrong (2/4)
48
+ RuntimeError: Something went wrong (3/4)
49
49
  Success!
50
50
  ```
51
51
 
@@ -54,29 +54,28 @@ The code above will produce the following output:
54
54
  Sometimes you want to only retry your code if a specific exception is raised. You can do this by passing a list of exceptions to the #tries method:
55
55
 
56
56
  ```rb
57
- 4.tries(rescue_from: [ZeroDivisionError, ArgumentError]) do |try|
58
- raise ZeroDivisionError if try < 2
59
- raise ActiveRecord::RecordInvalid if try < 4
60
- puts "Success!"
61
- end
57
+ 4.tries(rescue_from: [ZeroDivisionError, ArgumentError]) do |try|
58
+ raise ZeroDivisionError, 'Whoops' if try < 2
59
+ raise ActiveRecord::RecordInvalid if try < 4
60
+ puts "Success!"
61
+ end
62
62
  ```
63
63
 
64
64
  The code above will not rescue from the `ActiveRecord::RecordInvalid` error and produce the following output:
65
65
 
66
66
  ```
67
- Error: ZeroDivisionError (1/4)
67
+ ZeroDivisionError: Whoops (1/4)
68
68
  ActiveRecord::RecordInvalid: Record invalid
69
- from (pry):16:in `block in __pry__'
70
69
  ```
71
70
 
72
71
  Passing an array is not necessary if you need to only rescue from a single error
73
72
 
74
73
  ```rb
75
- 4.tries(rescue_from: ZeroDivisionError) do |try|
76
- raise ZeroDivisionError if try < 2
77
- raise ActiveRecord::RecordInvalid if try < 4
78
- puts "Success!"
79
- end
74
+ 4.tries(rescue_from: ZeroDivisionError) do |try|
75
+ raise ZeroDivisionError if try < 2
76
+ raise ActiveRecord::RecordInvalid if try < 4
77
+ puts "Success!"
78
+ end
80
79
  ```
81
80
 
82
81
  This will generate the same output.
@@ -86,19 +85,54 @@ This will generate the same output.
86
85
  EasyRetry gives you back the result of the first time the block you passed successfully runs. This can be useful when you need to use the result of the block for other tasks that you do not necessarily want to place in the block.
87
86
 
88
87
  ```rb
89
- result = 2.tries do |try|
90
- raise 'Woops' if try < 2
91
- "This is try number #{try}"
92
- end
88
+ result = 2.tries do |try|
89
+ raise 'Woops' if try < 2
90
+ "This is try number #{try}"
91
+ end
93
92
 
94
- puts result
93
+ puts result
95
94
  ```
96
95
 
97
96
  The code above will produce the following output.
98
97
 
99
98
  ```
100
- Error: Woops (1/2)
101
- => "This is try number 2"
99
+ RuntimeError: Woops (1/2)
100
+ => "This is try number 2"
101
+ ```
102
+
103
+ ## Custom delay
104
+
105
+ EasyRetry allows you to set the delay algorithm you want to use every time you call the `#tries` method. The following predefined options exist: `:none`, `:by_try`, `:default`, `:exponential`.
106
+
107
+ __*:none*__
108
+
109
+ After a try fails, EasyRetry will not wait and try again immediately.
110
+
111
+ __*:by_try*__
112
+
113
+ After a try fails, EasyRetry will wait an equal amount of seconds to current try that failed. I.e. 1 second for try one, 2 for try two, 3 for try three, etc.
114
+
115
+ __*:default*__
116
+
117
+ After a try fails, EasyRetry will wait _n^2_, where _n_ is the current try that failed.
118
+
119
+ __*:exponential*__
120
+
121
+ After a try fails, EasyRetry will wait _2^n_, where _n_ is the current try that failed.
122
+
123
+ ### Usage
124
+ You can use the predefined delay algorithms as follows:
125
+ ```rb
126
+ 3.tries(delay: :none) do
127
+ raise StandardError
128
+ end
129
+ ```
130
+
131
+ You can also define a custom lambda function if the predefined options are not meeting your needs. You can use it like this:
132
+ ```rb
133
+ 3.tries(delay: ->(current_try) { sleep current_try * 9.81 }) do
134
+ raise StandardError
135
+ end
102
136
  ```
103
137
 
104
138
  ## Configuration
@@ -106,9 +140,9 @@ The code above will produce the following output.
106
140
  You can configure EasyRetry by adding an initializer as follows:
107
141
 
108
142
  ```rb
109
- EasyRetry.configure do |config|
110
- # configuration options
111
- end
143
+ EasyRetry.configure do |config|
144
+ # configuration options
145
+ end
112
146
  ```
113
147
 
114
148
  ### Logger
@@ -116,21 +150,34 @@ You can configure EasyRetry by adding an initializer as follows:
116
150
  By default, EasyRetry uses [logger](https://rubygems.org/gems/logger) for logging errors. You can add your custom logger in the configuration using the `config.logger` option.
117
151
 
118
152
  ```rb
119
- # For Example, using Rails.logger
120
- config.logger = Rails.logger
153
+ # For Example, using Rails.logger
154
+ config.logger = Rails.logger
121
155
  ```
122
156
 
123
157
  NB: The logger should follow Rails Logger conventions.
124
158
 
159
+ ### Default Delay Algorithm
160
+ By default the `:default` delay algorithm (_n^2_) is used, what's in a name you could say. You can configure the default delay algorithm through the config as follows:
161
+
162
+ ```rb
163
+ config.delay_algorithm = :default # Or :none, :by_try, :exponential
164
+ ```
165
+
166
+ Of course, also here you can instead use a custom lambda delay:
167
+
168
+ ```rb
169
+ config.delay_algorithm = ->(current_try) { sleep current_try * 9.81 }
170
+ ```
171
+
125
172
  ## Retry delay
126
173
 
127
174
  The delay for each retry is based on the iteration count. The delay after each failed attempt is _n^2_, where _n_ is the current iteration that failed. E.g. after the first try, EasyRetry waits 1 second, after the second try it waits 4 seconds, then 9, then 16, then 25, then 36, etc.
128
175
 
129
176
  ## Development
130
177
 
131
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
178
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `be rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
132
179
 
133
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
180
+ To install this gem onto your local machine, run `bundle exec rake install`.
134
181
 
135
182
  ## Contributing
136
183
 
@@ -5,10 +5,11 @@ require 'logger'
5
5
  module EasyRetry
6
6
  # Configuration class
7
7
  class Configuration
8
- attr_accessor :logger
8
+ attr_accessor :logger, :delay_algorithm
9
9
 
10
10
  def initialize
11
11
  @logger = Logger.new($stdout)
12
+ @delay_algorithm = :default
12
13
  end
13
14
  end
14
15
  end
@@ -3,7 +3,7 @@
3
3
  # Extend the Numeric class with a #tries method
4
4
  class Numeric
5
5
  # rubocop:disable Metrics/MethodLength
6
- def tries(rescue_from: [StandardError])
6
+ def tries(rescue_from: [StandardError], delay: EasyRetry.delay_algorithm)
7
7
  raise ArgumentError, 'No block given' unless block_given?
8
8
 
9
9
  rescue_from = Array(rescue_from)
@@ -16,11 +16,9 @@ class Numeric
16
16
 
17
17
  break
18
18
  rescue *rescue_from => e
19
- EasyRetry.logger.info "#{e.class.name}: #{e.message} (#{current_try}/#{max_retry})"
19
+ log_failed_try(e, current_try, max_retry)
20
20
 
21
- raise if current_try >= max_retry
22
-
23
- sleep current_try * current_try
21
+ call_delay(delay, current_try)
24
22
 
25
23
  current_try += 1
26
24
  end
@@ -30,4 +28,23 @@ class Numeric
30
28
  # rubocop:enable Metrics/MethodLength
31
29
 
32
30
  alias try tries
31
+
32
+ private
33
+
34
+ def call_delay(delay, current_try)
35
+ return delay.call(current_try) if delay.is_a?(Proc)
36
+
37
+ EasyRetry.delay_options[delay].call(current_try)
38
+ end
39
+
40
+ def log_failed_try(error, current_try, max_retry)
41
+ message = error.message == error.class.name ? ' ' : ": #{error.message} "
42
+
43
+ if current_try >= max_retry
44
+ EasyRetry.logger.info "FAILED Permanently after #{max_retry} tries; #{error.class.name}#{message}".strip
45
+ raise
46
+ else
47
+ EasyRetry.logger.info "#{error.class.name}#{message}(Try Number #{current_try}/#{max_retry})"
48
+ end
49
+ end
33
50
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EasyRetry
4
- VERSION = "1.0.7"
4
+ VERSION = '1.0.8.1'
5
5
  end
data/lib/easy_retry.rb CHANGED
@@ -18,5 +18,18 @@ module EasyRetry
18
18
  def logger
19
19
  configuration.logger
20
20
  end
21
+
22
+ def delay_algorithm
23
+ configuration.delay_algorithm
24
+ end
25
+
26
+ def delay_options
27
+ {
28
+ none: ->(_try_number) {},
29
+ by_try: ->(try_number) { sleep try_number },
30
+ default: ->(try_number) { sleep try_number * try_number },
31
+ exponential: ->(try_number) { sleep 2**try_number }
32
+ }
33
+ end
21
34
  end
22
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_retry
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robin Goudeketting, Peter Duijnstee
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-23 00:00:00.000000000 Z
11
+ date: 2022-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logger
@@ -24,6 +24,62 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.5.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.21'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.21'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
27
83
  description: Easily retry a block of code a predetermined number of times
28
84
  email:
29
85
  - robin@goudeketting.nl