faraday-retry 2.2.1 → 2.3.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: 4215b6f0b7dd61fa8702103e77d6373cace2c46b469defeb0ed93ce94aa26e6c
4
- data.tar.gz: 295faca61565e49a36a7f03201d6aee90b6a353c40d22a8bf8e1f6b1c729c041
3
+ metadata.gz: af805c058f1e08fba4ab4c53587f88906f086f06bda02dd4daf578123d6aa79f
4
+ data.tar.gz: 714eeaadf0d8021d7c33f86ece4dda66366fcc6525e8bf395c3e71591d0a8bc2
5
5
  SHA512:
6
- metadata.gz: 5b8f2bee0e35492efc578659ce28a0b947374c8cafdba07606d953c417e8844128248a639392e4ad60c682528c0d478d3a894ca688e1f72965172633aee3be7f
7
- data.tar.gz: 148ac2094f76cd59ea9278a4d1948b3211f0c2abc1876b6f10fbdd88a384257dfdfab33f9a1cf102ed23352b5b0dd2e9f1f4d533cd8459c4b86d1f5e7578a053
6
+ metadata.gz: 6de30437afefef5b6887a0c7b2e72615775b63a92aaee63c37672631d9e09011b0b46fa9c208e6ca280d55ace287e12c9077ed18107968bc5593255cd028b6c1
7
+ data.tar.gz: dc0e7f4b11e714addd9a11426cc5071eb2245ea8f5cb24a38e7f63ee50030df81b14380912b4f0b786f9bfa53dfeccbc16f802337638054d7e36ad56be667f3f
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ _nothing yet_
6
+
7
+ ## v2.2.1 (2024-04-15)
8
+
5
9
  * Avoid deprecation warning about ::UploadIO constant when used without faraday-multipart gem [PR #37](https://github.com/lostisland/faraday-retry/pull/37) [@iMacTia]
6
10
  * Documentation update [PR #30](https://github.com/lostisland/faraday-retry/pull/30) [@olleolleolle]
7
11
  * Documentation update [PR #32](https://github.com/lostisland/faraday-retry/pull/32) Thanks, [@Drowze]!
data/README.md CHANGED
@@ -149,8 +149,8 @@ retry_options = {
149
149
 
150
150
  ### Call a block on every retry
151
151
 
152
- You can specify a proc object through the `retry_block` option that will be called before every
153
- retry, before There are many different applications for this feature, spacing from instrumentation to monitoring.
152
+ You can specify a proc object through the `retry_block` option that will be called before every retry.
153
+ There are many different applications for this feature, ranging from instrumentation to monitoring.
154
154
 
155
155
  The block is passed keyword arguments with contextual information: Request environment, middleware options, current number of retries, exception, and amount of time we will wait before retrying. (retry_block is called before the wait time happens)
156
156
 
@@ -163,6 +163,27 @@ retry_options = {
163
163
  }
164
164
  ```
165
165
 
166
+ ### Call a block after retries have been exhausted
167
+
168
+ You can specify a lambda object through the `exhausted_retries_block` option that will be called after all retries are exhausted.
169
+ This block will be called once.
170
+
171
+ The block is passed keyword arguments with contextual information and passed your data:
172
+ * Request environment,
173
+ * exception,
174
+ * middleware options
175
+ * and your data.
176
+
177
+ In a lambda you can pass any logic for further work.
178
+
179
+ For example, you might want to update user by request query.
180
+
181
+ ```ruby
182
+ retry_options = {
183
+ exhausted_retries_block: -> (user_id:, env:, exception:, options:) { User.find_by!(id: user_id).do_admin! }
184
+ }
185
+ ```
186
+
166
187
  ## Development
167
188
 
168
189
  After checking out the repo, run `bin/setup` to install dependencies.
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'retryable'
4
+
3
5
  module Faraday
4
6
  module Retry
5
7
  # This class provides the main implementation for your middleware.
@@ -15,6 +17,8 @@ module Faraday
15
17
  # (see "retry" middleware: https://github.com/lostisland/faraday/blob/main/lib/faraday/request/retry.rb#L142).
16
18
  # IMPORTANT: Remember to call `@app.call(env)` or `super` to not interrupt the middleware chain!
17
19
  class Middleware < Faraday::Middleware
20
+ include Retryable
21
+
18
22
  DEFAULT_EXCEPTIONS = [
19
23
  Errno::ETIMEDOUT, 'Timeout::Error',
20
24
  Faraday::TimeoutError, Faraday::RetriableResponse
@@ -27,7 +31,8 @@ module Faraday
27
31
  :backoff_factor, :exceptions,
28
32
  :methods, :retry_if, :retry_block,
29
33
  :retry_statuses, :rate_limit_retry_header,
30
- :rate_limit_reset_header, :header_parser_block)
34
+ :rate_limit_reset_header, :header_parser_block,
35
+ :exhausted_retries_block)
31
36
 
32
37
  DEFAULT_CHECK = ->(_env, _exception) { false }
33
38
 
@@ -78,6 +83,10 @@ module Faraday
78
83
  def retry_statuses
79
84
  Array(self[:retry_statuses] ||= [])
80
85
  end
86
+
87
+ def exhausted_retries_block
88
+ self[:exhausted_retries_block] ||= proc {}
89
+ end
81
90
  end
82
91
 
83
92
  # @param app [#call]
@@ -124,6 +133,13 @@ module Faraday
124
133
  # the the value of the retry header and should return the number of
125
134
  # seconds to wait before retrying the request. This is useful if the
126
135
  # value of the header is not a number of seconds or a RFC 2822 formatted date.
136
+ # @option options [Block] :exhausted_retries_block block will receive
137
+ # when all attempts are exhausted. The block will be yielded keyword arguments:
138
+ # * env [Faraday::Env]: Request environment
139
+ # * exception [Exception]: exception that triggered the retry,
140
+ # will be the synthetic `Faraday::RetriableResponse` if the
141
+ # retry was triggered by something other than an exception.
142
+ # * options [Faraday::Options]: middleware options
127
143
  def initialize(app, options = nil)
128
144
  super(app)
129
145
  @options = Options.from(options)
@@ -147,32 +163,14 @@ module Faraday
147
163
  def call(env)
148
164
  retries = @options.max
149
165
  request_body = env[:body]
150
- begin
166
+
167
+ with_retries(env: env, options: @options, retries: retries, body: request_body, errmatch: @errmatch) do
151
168
  # after failure env[:body] is set to the response body
152
169
  env[:body] = request_body
170
+
153
171
  @app.call(env).tap do |resp|
154
172
  raise Faraday::RetriableResponse.new(nil, resp) if @options.retry_statuses.include?(resp.status)
155
173
  end
156
- rescue @errmatch => e
157
- if retries.positive? && retry_request?(env, e)
158
- retries -= 1
159
- rewind_files(request_body)
160
- if (sleep_amount = calculate_sleep_amount(retries + 1, env))
161
- @options.retry_block.call(
162
- env: env,
163
- options: @options,
164
- retry_count: @options.max - (retries + 1),
165
- exception: e,
166
- will_retry_in: sleep_amount
167
- )
168
- sleep sleep_amount
169
- retry
170
- end
171
- end
172
-
173
- raise unless e.is_a?(Faraday::RetriableResponse)
174
-
175
- e.response
176
174
  end
177
175
  end
178
176
 
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Adds the ability to retry a request based on settings and errors that have occurred.
4
+ module Retryable
5
+ def with_retries(env:, options:, retries:, body:, errmatch:)
6
+ yield
7
+ rescue errmatch => e
8
+ exhausted_retries(options, env, e) if retries_zero?(retries, env, e)
9
+
10
+ if retries.positive? && retry_request?(env, e)
11
+ retries -= 1
12
+ rewind_files(body)
13
+ if (sleep_amount = calculate_sleep_amount(retries + 1, env))
14
+ options.retry_block.call(
15
+ env: env,
16
+ options: options,
17
+ retry_count: options.max - (retries + 1),
18
+ exception: e,
19
+ will_retry_in: sleep_amount
20
+ )
21
+ sleep sleep_amount
22
+ retry
23
+ end
24
+ end
25
+
26
+ raise unless e.is_a?(Faraday::RetriableResponse)
27
+
28
+ e.response
29
+ end
30
+
31
+ private
32
+
33
+ def retries_zero?(retries, env, exception)
34
+ retries.zero? && retry_request?(env, exception)
35
+ end
36
+
37
+ def exhausted_retries(options, env, exception)
38
+ options.exhausted_retries_block.call(
39
+ env: env,
40
+ exception: exception,
41
+ options: options
42
+ )
43
+ end
44
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Faraday
4
4
  module Retry
5
- VERSION = '2.2.1'
5
+ VERSION = '2.3.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faraday-retry
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattia Giuffrida
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-15 00:00:00.000000000 Z
11
+ date: 2025-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -151,17 +151,18 @@ files:
151
151
  - lib/faraday/retriable_response.rb
152
152
  - lib/faraday/retry.rb
153
153
  - lib/faraday/retry/middleware.rb
154
+ - lib/faraday/retry/retryable.rb
154
155
  - lib/faraday/retry/version.rb
155
156
  homepage: https://github.com/lostisland/faraday-retry
156
157
  licenses:
157
158
  - MIT
158
159
  metadata:
159
160
  bug_tracker_uri: https://github.com/lostisland/faraday-retry/issues
160
- changelog_uri: https://github.com/lostisland/faraday-retry/blob/v2.2.1/CHANGELOG.md
161
- documentation_uri: http://www.rubydoc.info/gems/faraday-retry/2.2.1
161
+ changelog_uri: https://github.com/lostisland/faraday-retry/blob/v2.3.0/CHANGELOG.md
162
+ documentation_uri: http://www.rubydoc.info/gems/faraday-retry/2.3.0
162
163
  homepage_uri: https://github.com/lostisland/faraday-retry
163
164
  source_code_uri: https://github.com/lostisland/faraday-retry
164
- post_install_message:
165
+ post_install_message:
165
166
  rdoc_options: []
166
167
  require_paths:
167
168
  - lib
@@ -180,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
181
  version: '0'
181
182
  requirements: []
182
183
  rubygems_version: 3.1.6
183
- signing_key:
184
+ signing_key:
184
185
  specification_version: 4
185
186
  summary: Catches exceptions and retries each request a limited number of times
186
187
  test_files: []