Skip to content

Commit ffef0dd

Browse files
committed
retry_block takes keyword arguments, and has a new one for will_retry_in seconds
1 parent 15af77f commit ffef0dd

File tree

4 files changed

+46
-9
lines changed

4 files changed

+46
-9
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
## v2.0
4+
5+
### Changed
6+
7+
* retry_block now takes keyword arguments instead of positional (backwards incompatible)
8+
9+
### Added
10+
11+
* retry_block has additional `will_retry_in` argument with upcoming delay before retry in seconds.
12+
313
## v1.0
414

515
Initial release.

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,19 @@ retry_options = {
127127

128128
### Call a block on every retry
129129

130-
You can specify a block through the `retry_block` option that will be called before every retry.
131-
There are many different applications for this feature, spacing from instrumentation to monitoring.
132-
Request environment, middleware options, current number of retries and the exception is passed to the block as parameters.
130+
You can specify a proc object through the `retry_block` option that will be called before every
131+
retry, before There are many different applications for this feature, spacing from instrumentation to monitoring.
132+
133+
134+
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)
135+
136+
133137
For example, you might want to keep track of the response statuses:
134138

135139
```ruby
136140
response_statuses = []
137141
retry_options = {
138-
retry_block: -> (env, options, retries, exc) { response_statuses << env.status }
142+
retry_block: -> (env:, options:, retries_remaining:, exception:, will_retry_in:) { response_statuses << env.status }
139143
}
140144
```
141145

lib/faraday/retry/middleware.rb

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,17 @@ def retry_statuses
105105
# if the exception produced is non-recoverable or if the
106106
# the HTTP method called is not idempotent.
107107
# @option options [Block] :retry_block block that is executed before
108-
# every retry. Request environment, middleware options, current number
109-
# of retries and the exception is passed to the block as parameters.
108+
# every retry. The block will be yielded keyword arguments:
109+
# * env [Faraday::Env]: Request environment
110+
# * options [Faraday::Options]: middleware options
111+
# * retries_remaining [Integer]: how many more possible retries are
112+
# remaining
113+
# * exception [Exception]: exception that triggered the retry,
114+
# will be the synthetic `Faraday::RetriableResponse` if the
115+
# retry was triggered by something other than an exception.
116+
# * will_retry_in [Float]: retry_block is called *before* the retry
117+
# delay, actual retry will happen in will_retry_in number of
118+
# seconds.
110119
# @option options [Array] :retry_statuses Array of Integer HTTP status
111120
# codes or a single Integer value that determines whether to raise
112121
# a Faraday::RetriableResponse exception based on the HTTP status code
@@ -145,7 +154,13 @@ def call(env)
145154
retries -= 1
146155
rewind_files(request_body)
147156
if (sleep_amount = calculate_sleep_amount(retries + 1, env))
148-
@options.retry_block.call(env, @options, retries, e)
157+
@options.retry_block.call(
158+
env: env,
159+
options: @options,
160+
retries_remaining: retries,
161+
exception: e,
162+
will_retry_in: sleep_amount
163+
)
149164
sleep sleep_amount
150165
retry
151166
end

spec/faraday/retry/middleware_spec.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,21 @@
8787
end
8888

8989
context 'and retry_block is set' do
90-
let(:options) { [{ retry_block: ->(env, options, retries, exc) { retry_block_calls << [env, options, retries, exc] } }] }
90+
let(:options) { [{ retry_block: ->(**kwargs) { retry_block_calls << kwargs } }] }
9191
let(:retry_block_calls) { [] }
9292
let(:retry_block_times_called) { retry_block_calls.size }
9393

9494
it 'calls retry block for each retry' do
9595
expect(retry_block_times_called).to eq(2)
9696
end
97+
98+
it "has appropriate args to retry_block" do
99+
expect(retry_block_calls.first[:exception]).to be_kind_of(Errno::ETIMEDOUT)
100+
expect(retry_block_calls.first[:options]).to be_kind_of(Faraday::Options)
101+
expect(retry_block_calls.first[:env]).to be_kind_of(Faraday::Env)
102+
expect(retry_block_calls.first[:will_retry_in]).to be_kind_of(Float)
103+
expect(retry_block_calls.first[:retries_remaining]).to eq 1
104+
end
97105
end
98106
end
99107

@@ -263,7 +271,7 @@
263271
context 'and retry_block is set' do
264272
let(:options) do
265273
[{
266-
retry_block: ->(env, options, retries, exc) { retry_block_calls << [env, options, retries, exc] },
274+
retry_block: ->(**kwargs) { retry_block_calls << kwargs },
267275
max: 2,
268276
max_interval: 5,
269277
retry_statuses: 504

0 commit comments

Comments
 (0)