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

Add .retriable feature to Http #598

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open

Add .retriable feature to Http #598

wants to merge 10 commits into from

Conversation

Bertg
Copy link

@Bertg Bertg commented Mar 5, 2020

Based on the great initial POC of @ixti this should complete #595

  • Delay by default backs backs off over time
  • Maximum delay time
  • Exceptions to retry from
  • Status codes to retry from
  • Custom retry logic
  • Respect Retry-After header if present
  • on_retry callback

Remarks:

  • RuboCop report is clean
  • Tried to manually update the method comments, but I'm not sure if that is correct

ixti and others added 3 commits March 5, 2020 11:49
* Delay by default backs backs off over time
* Maximum delay time
* Exceptions to retry from
* Status codes to retry from
* Custom retry logic
* Respect Retry-After header if present
* on_retry callback
@Bertg
Copy link
Author

Bertg commented Mar 5, 2020

@paul & @ixti If you have any remarks on the PR, let me know, and I'll see to them

@ixti
Copy link
Member

ixti commented Mar 9, 2020

I had no time to do a full review, but there's one thing that I would like to be changed. Default list of statuses to retry should be 5XX. So probably for statuses it's better to provide proc.

@Bertg
Copy link
Author

Bertg commented Mar 9, 2020

@ixti Took your feedback, and made the 500+ range auto retry.

However, I would argue that the library should not rely any status code by default. Here is why:

When a server is throwing 500 there is a good chance that it is experiencing trouble. By retrying by default we are making the situation worse. The same logic if followed in the faraday gem.

@Bertg
Copy link
Author

Bertg commented Mar 9, 2020

I'll also wait to to comply with the code climate feedback, until the all human feedback is processed ;)

Copy link
Member

@ixti ixti left a comment

Choose a reason for hiding this comment

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

I think handling different types of retry statuses is unneeded complication and supporting proc only is more than enough - it will handle all the cases. Also I think exception retry proc and status retry should be separated.

lib/http/retriable/performer.rb Outdated Show resolved Hide resolved
lib/http/retriable/performer.rb Outdated Show resolved Hide resolved
@Bertg
Copy link
Author

Bertg commented Mar 9, 2020

I think handling different types of retry statuses is unneeded complication and supporting proc only is more than enough - it will handle all the cases.

The idea is to allow for a beautiful interface for the developer.

HTTP.retriable(retry_statuses: 400..499)
HTTP.retriable(retry_statuses: [404, 500..599])

looks a lot better than

HTTP.retriable(retry_statuses: ->(s) {  (400..499).cover?(s) })
HTTP.retriable((retry_statuses: ->(s) { s == 404 || (400..499).cover?(s) })

I could move that convienece into Chainable#retriable but I don't believe that is the best place for it.

Also I think exception retry proc and status retry should be separated.

I get that. However one of the options a developer can pass is a proc should_retry to decide to retry or not, based on exception or status code. I'm trying to use the same logic here.
I guess I could make a method that looks something like this:

def perform(client, req)
  1.upto(Float::INFINITY) do |attempt| # infinite loop with index
    err, res = try_request { yield }

    if retry_request?(req, err, res, attempt)
      begin
        wait_for_retry_or_raise(req, err, res, attempt)
      ensure
        # ...
        client.close
      end
    elsif err
      client.close
      raise err
    elsif res
      return res
    end
  end
end

def retry_request?(req, err, res, attempt)
  if options[:should_retry]
    options[:should_retry].call(req, err, res, attempt)
  elsif err
    options[:exceptions].any? {|err_class| err.is_a?(err_class) }
  else
    options[:retry_statuses].cover?(req.status)
  end
end

Would you prefer this?

* Less procs & proc building overall
* seperate delay calculation into its own class
@Bertg
Copy link
Author

Bertg commented Mar 13, 2020

Made some updates!

  • extracted the delay logic into its own class
  • less procs & proc building overall
  • stopped handling 500+ HTTP status codes by default (see previous comment for argumentation)

@Bertg
Copy link
Author

Bertg commented Mar 19, 2020

Anything I can do to help progress this PR towards merging?

@rkhapre
Copy link

rkhapre commented Oct 23, 2020

This is available now in Pre 5.x releases?

@yashtewari
Copy link

Any updates on this? @ixti are you still in favor of adding retry functionality to Http?

@tarcieri
Copy link
Member

The 5.x release is out. If you are still interested in pursuing this, can you rebase?

@czj
Copy link

czj commented Jun 5, 2023

I would still love to get this PR merged :-)
Is there any way we could help @levups ?

@ixti
Copy link
Member

ixti commented Jun 5, 2023

I can try to take a look on this next week.

@ixti ixti self-assigned this Jun 5, 2023
@ixti ixti added the Feature label Jun 5, 2023
@czj
Copy link

czj commented Jun 6, 2023

That's very kind @ixti ! Thank you.

@tomprats
Copy link

tomprats commented Jan 5, 2024

Would love to have this. I looked into major changes since it's release and besides the hashrocket one, I don't think anything changed to break this.

@ixti would you mind taking a look again?

If you want, I can rebase, but I think if I do it, it'd have to go into a new PR

@ixti
Copy link
Member

ixti commented Jan 15, 2024

Sorry been swamped with lots of stuff. Will take a look at the rebased PR as soon as possible. And hope to make it land this month :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants