diff --git a/README.md b/README.md index bffecfe8a..ba731494f 100644 --- a/README.md +++ b/README.md @@ -597,7 +597,7 @@ traffic: ```ruby stack = Faraday::RackBuilder.new do |builder| - builder.use Faraday::Retry::Middleware, exceptions: Faraday::Retry::Middleware::DEFAULT_EXCEPTIONS + [Octokit::ServerError] # or Faraday::Request::Retry for Faraday < 2.0 + builder.use Octokit::Middleware::Retry builder.use Octokit::Middleware::FollowRedirects builder.use Octokit::Response::RaiseError builder.use Octokit::Response::FeedParser @@ -631,6 +631,22 @@ x-ratelimit-reset: "1377205443" See the [Faraday README][faraday] for more middleware magic. +### Retrying + +If you want to retry requests, use `Octokit::Middleware::Retry`. + +It uses [Faraday Retry gem] for Faraday 2.x. Add the gem to your Gemfile + +```ruby +gem 'faraday-retry' +``` + +Next, insert `Octokit::Middleware::Retry` before `Octokit::Response::RaiseError`: + +```ruby +Octokit.middleware.insert Octokit::Response::RaiseError, Octokit::Middleware::Retry +``` + ### Caching If you want to boost performance, stretch your API rate limit, or avoid paying @@ -655,6 +671,7 @@ Once configured, the middleware will store responses in cache based on ETag fingerprint and serve those back up for future `304` responses for the same resource. See the [project README][cache] for advanced usage. +[retry]: https://github.com/lostisland/faraday-retry [cache]: https://github.com/sourcelevel/faraday-http-cache [faraday]: https://github.com/lostisland/faraday diff --git a/lib/octokit.rb b/lib/octokit.rb index b029d8bc9..db9c9fcbd 100644 --- a/lib/octokit.rb +++ b/lib/octokit.rb @@ -76,6 +76,12 @@ def method_missing(method_name, *args, &block) super end end + + module Middleware + # In Faraday 2.x, Faraday::Request::Retry was moved to a separate gem + # so we use it only when requested. + autoload :Retry, 'octokit/middleware/retry' + end end Octokit.setup diff --git a/lib/octokit/default.rb b/lib/octokit/default.rb index ca2e2fb73..3d4d84833 100644 --- a/lib/octokit/default.rb +++ b/lib/octokit/default.rb @@ -6,14 +6,6 @@ require 'octokit/version' require 'octokit/warnable' -if Gem::Version.new(Faraday::VERSION) >= Gem::Version.new('2.0') - begin - require 'faraday/retry' - rescue LoadError - Octokit::Warnable.octokit_warn 'To use retry middleware with Faraday v2.0+, install `faraday-retry` gem' - end -end - module Octokit # Default configuration options for {Client} module Default @@ -31,16 +23,6 @@ module Default # Default Faraday middleware stack MIDDLEWARE = Faraday::RackBuilder.new do |builder| - # In Faraday 2.x, Faraday::Request::Retry was moved to a separate gem - # so we use it only when it's available. - if defined?(Faraday::Request::Retry) - retry_exceptions = Faraday::Request::Retry::DEFAULT_EXCEPTIONS + [Octokit::ServerError] - builder.use Faraday::Request::Retry, exceptions: retry_exceptions - elsif defined?(Faraday::Retry::Middleware) - retry_exceptions = Faraday::Retry::Middleware::DEFAULT_EXCEPTIONS + [Octokit::ServerError] - builder.use Faraday::Retry::Middleware, exceptions: retry_exceptions - end - builder.use Octokit::Middleware::FollowRedirects builder.use Octokit::Response::RaiseError builder.use Octokit::Response::FeedParser @@ -147,7 +129,7 @@ def login # from {MIDDLEWARE} # @return [Faraday::RackBuilder or Faraday::Builder] def middleware - MIDDLEWARE + MIDDLEWARE.dup end # Default GitHub password for Basic Auth from ENV diff --git a/lib/octokit/middleware/retry.rb b/lib/octokit/middleware/retry.rb new file mode 100644 index 000000000..f442b16eb --- /dev/null +++ b/lib/octokit/middleware/retry.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Octokit + module Middleware + base = if defined?(Faraday::Request::Retry) + Faraday::Request::Retry + else + require 'faraday/retry' + Faraday::Retry::Middleware + end + + # Public: Retries each request a limited number of times. + class Retry < base + def initialize(app, **kwargs) + super(app, **kwargs, exceptions: DEFAULT_EXCEPTIONS + [Octokit::ServerError]) + end + end + end +end diff --git a/spec/octokit/client_spec.rb b/spec/octokit/client_spec.rb index 3d3d81fcd..3b5f6458b 100644 --- a/spec/octokit/client_spec.rb +++ b/spec/octokit/client_spec.rb @@ -514,6 +514,27 @@ end end + describe 'retry' do + it 'retries for 504 response' do + client = oauth_client + client.middleware.insert Octokit::Response::RaiseError, Octokit::Middleware::Retry + + requested = false + + request = stub_get('/foo').to_return do + if requested + { status: 200 } + else + requested = true + { status: 504 } + end + end + + client.get('/foo') + assert_requested request, times: 2 + end + end + describe 'redirect handling' do it 'follows redirect for 301 response' do client = oauth_client