diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e17b9bd..932c4be 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2021-12-31 12:13:51 UTC using RuboCop version 1.21.0. +# on 2022-01-04 18:53:25 UTC using RuboCop version 1.23.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -15,12 +15,12 @@ Lint/AmbiguousBlockAssociation: # Offense count: 1 # Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: - Max: 23 + Max: 26 # Offense count: 2 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. Metrics/MethodLength: - Max: 20 + Max: 26 # Offense count: 12 # Configuration parameters: Prefixes. @@ -49,11 +49,11 @@ RSpec/InstanceVariable: RSpec/MultipleExpectations: Max: 3 -# Offense count: 7 +# Offense count: 9 # Configuration parameters: AllowSubject. RSpec/MultipleMemoizedHelpers: Max: 9 -# Offense count: 1 +# Offense count: 3 RSpec/NestedGroups: Max: 4 diff --git a/CHANGELOG.md b/CHANGELOG.md index b24555c..e4193e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## v2.0 + +### Changed + +* retry_block now takes keyword arguments instead of positional (backwards incompatible) +* retry_block `retry_count` arg now counts up from 0, instead of old `retries_remaining` + +### Added + +* retry_block has additional `will_retry_in` argument with upcoming delay before retry in seconds. + ## v1.0 Initial release. diff --git a/README.md b/README.md index 884410b..c8ed0ee 100644 --- a/README.md +++ b/README.md @@ -127,15 +127,19 @@ retry_options = { ### Call a block on every retry -You can specify a block through the `retry_block` option that will be called before every retry. -There are many different applications for this feature, spacing from instrumentation to monitoring. -Request environment, middleware options, current number of retries and the exception is passed to the block as parameters. +You can specify a proc object through the `retry_block` option that will be called before every +retry, before There are many different applications for this feature, spacing from instrumentation to monitoring. + + +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) + + For example, you might want to keep track of the response statuses: ```ruby response_statuses = [] retry_options = { - retry_block: -> (env, options, retries, exc) { response_statuses << env.status } + retry_block: -> (env:, options:, retries_remaining:, exception:, will_retry_in:) { response_statuses << env.status } } ``` diff --git a/lib/faraday/retry/middleware.rb b/lib/faraday/retry/middleware.rb index 14778df..75dc0a9 100644 --- a/lib/faraday/retry/middleware.rb +++ b/lib/faraday/retry/middleware.rb @@ -105,8 +105,16 @@ def retry_statuses # if the exception produced is non-recoverable or if the # the HTTP method called is not idempotent. # @option options [Block] :retry_block block that is executed before - # every retry. Request environment, middleware options, current number - # of retries and the exception is passed to the block as parameters. + # every retry. The block will be yielded keyword arguments: + # * env [Faraday::Env]: Request environment + # * options [Faraday::Options]: middleware options + # * retry_count [Integer]: how many retries have already occured (starts at 0) + # * exception [Exception]: exception that triggered the retry, + # will be the synthetic `Faraday::RetriableResponse` if the + # retry was triggered by something other than an exception. + # * will_retry_in [Float]: retry_block is called *before* the retry + # delay, actual retry will happen in will_retry_in number of + # seconds. # @option options [Array] :retry_statuses Array of Integer HTTP status # codes or a single Integer value that determines whether to raise # a Faraday::RetriableResponse exception based on the HTTP status code @@ -145,7 +153,13 @@ def call(env) retries -= 1 rewind_files(request_body) if (sleep_amount = calculate_sleep_amount(retries + 1, env)) - @options.retry_block.call(env, @options, retries, e) + @options.retry_block.call( + env: env, + options: @options, + retry_count: @options.max - (retries + 1), + exception: e, + will_retry_in: sleep_amount + ) sleep sleep_amount retry end diff --git a/spec/faraday/retry/middleware_spec.rb b/spec/faraday/retry/middleware_spec.rb index f38de5e..15699d5 100644 --- a/spec/faraday/retry/middleware_spec.rb +++ b/spec/faraday/retry/middleware_spec.rb @@ -87,13 +87,25 @@ end context 'and retry_block is set' do - let(:options) { [{ retry_block: ->(env, options, retries, exc) { retry_block_calls << [env, options, retries, exc] } }] } + let(:options) { [{ retry_block: ->(**kwargs) { retry_block_calls << kwargs } }] } let(:retry_block_calls) { [] } let(:retry_block_times_called) { retry_block_calls.size } it 'calls retry block for each retry' do expect(retry_block_times_called).to eq(2) end + + describe 'with arguments to retry_block' do + it { expect(retry_block_calls.first[:exception]).to be_kind_of(Errno::ETIMEDOUT) } + it { expect(retry_block_calls.first[:options]).to be_kind_of(Faraday::Options) } + it { expect(retry_block_calls.first[:env]).to be_kind_of(Faraday::Env) } + it { expect(retry_block_calls.first[:retry_count]).to be_kind_of(Integer) } + it { expect(retry_block_calls.first[:retry_count]).to eq 0 } + end + + describe 'arguments to retry_block on second call' do + it { expect(retry_block_calls[1][:retry_count]).to eq 1 } + end end end @@ -263,7 +275,7 @@ context 'and retry_block is set' do let(:options) do [{ - retry_block: ->(env, options, retries, exc) { retry_block_calls << [env, options, retries, exc] }, + retry_block: ->(**kwargs) { retry_block_calls << kwargs }, max: 2, max_interval: 5, retry_statuses: 504