Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not warn even if faraday-retry gem is missing #1706

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ traffic:

```ruby
stack = Faraday::RackBuilder.new do |builder|
builder.use Faraday::Retry::Middleware, exceptions: Faraday::Request::Retry::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
Expand Down Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think configuring it on the client would be better

Octokit::Client.new(auto_retry: true)

and then in the connection sawyer options you can insert the retry middleware if @auto_retry

conn_opts[:builder].insert(0, *retry_middleware) if @auto_retry

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While having a parameter for Octokit::Client.new is more concise, there are a few advantages of explicitly requiring to interact with middleware:

  1. A user can specify additional options.
  2. It is clear that it interacts with middleware.
  3. It is consistent with the suggestion for caching, which follows this section in README.md.

So there is some trade-off. What do you prefer?

Copy link
Contributor

@pbstriker38 pbstriker38 Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if you want one client that retries and another that doesn't. Setting on Octokit.middleware is global.

You probably also want a maintainer to chime in here...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

```

### Caching

If you want to boost performance, stretch your API rate limit, or avoid paying
Expand All @@ -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

Expand Down
6 changes: 6 additions & 0 deletions lib/octokit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 1 addition & 19 deletions lib/octokit/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This warning is the only thing that would even let you know that this gem does retries. There is nothing in the README about this. This would be better as an explicit option to enable retries.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do you suggest disabling retries by default?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be the best way to remove the warning. The retry functionality needs to be better documented.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added commit 3395ed4 to remove the retry middleware from the default middleware stack and commit c892eb3 to provide the retry middleware to insert it into the middleware stack explicitly.

end
end

module Octokit
# Default configuration options for {Client}
module Default
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
19 changes: 19 additions & 0 deletions lib/octokit/middleware/retry.rb
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions spec/octokit/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down