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

Allow Features to handle connection errors #552

Merged
merged 1 commit into from
Oct 21, 2019

Conversation

joshuaflanagan
Copy link
Contributor

This addresses #547

It allows a Feature to implement an on_error handler so that it has a chance to react to Requests that never get a Response.

@joshuaflanagan joshuaflanagan force-pushed the instrument_errors branch 2 times, most recently from 4f9756c to c02c0cb Compare May 20, 2019 23:51
joshuaflanagan added a commit to ShippingEasy/http that referenced this pull request May 20, 2019
This mirrors httprb#552, which has not been merged yet
joshuaflanagan added a commit to ShippingEasy/http that referenced this pull request May 21, 2019
This mirrors httprb#552, which has not been merged yet
@tarcieri
Copy link
Member

Looks like you need to fix the RuboCop errors. Otherwise conceptually this seems ok to me.

@ixti what do you think?

@tarcieri
Copy link
Member

@paul any thoughts on this approach, or suggested alternatives?

@paul
Copy link
Contributor

paul commented Jun 26, 2019

@tarcieri No, this seems fine to me. 👍

@connection.read_headers!
end
rescue Error => e
options.features.each do |_name, feature|
Copy link
Member

Choose a reason for hiding this comment

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

I think you can do each_value here (and potentially collapse it into a 1-liner), e.g.:

options.features.each_value { |feature| feature.on_error(req, e) }

@joshuaflanagan
Copy link
Contributor Author

Looks like you need to fix the RuboCop errors. Otherwise conceptually this seems ok to me.

It is difficult as an outside contributor to understand which rubocop rules a team cares about. Were each of the rules chosen because they are what the team values? Or were they just the defaults?

For example, this project currently has the Metrics/MethodLength rule enabled, so this PR has this violation:

lib/http/client.rb:66:5: C: Metrics/MethodLength: Method has too many lines. [32/25]
    def perform(req, options)

Is it really appropriate for this PR to take on the task of refactoring the Client#perform method so that it isn't so long?

Or should I disable the rule? Or just exclude this file? Or just exclude this method?

@tarcieri
Copy link
Member

It is difficult as an outside contributor to understand which rubocop rules a team cares about. Were each of the rules chosen because they are what the team values? Or were they just the defaults?

It's explicitly configured to 25 lines in .rubocop.yml. To answer your question: yes this project values smaller methods.

Is it really appropriate for this PR to take on the task of refactoring the Client#perform method so that it isn't so long?

If you really don't want to refactor it you can disable the check for this method in particular using rubocop:disable and leave it for someone else to refactor. At the very least the RuboCop check needs to pass.

That said it looks like Response.new could benefit from some refactoring and is the source of much of the methods bulk by lines.

@joshuaflanagan
Copy link
Contributor Author

If you really don't want to refactor it you can disable the check for this method in particular using rubocop:disable and leave it for someone else to refactor. At the very least the RuboCop check needs to pass.

I don't mind doing the refactor, I just thought it was out of scope for this task, and would obscure the point of this PR. I'll go ahead and disable the rule here, and leave it as a follow up issue.

@ixti
Copy link
Member

ixti commented Jun 26, 2019

What if error will happen down the course, e.g. during response streaming?

@tarcieri
Copy link
Member

tarcieri commented Jun 28, 2019

@ixti it seems like under this approach features wouldn't be able to handle those errors, however it seems like they can handle the most interesting errors, i.e. immediate response errors

@joshuaflanagan
Copy link
Contributor Author

I have rebased and addressed the rubocop issues.

@ixti
Copy link
Member

ixti commented Jul 18, 2019

Thank you!

I have taken another look, and I think we can make API a bit more "flexible" if we will rename on_error to observe:

def observe(event, data); end

# ...

options.features.each_value { |f| f.observe(:request_error, :req => self, :err => e) }

Just an idea. As I don't like on_error name it's too vague, while used in very specific case only. Also, probably we should add observers in general instead of bloating this functionality into features.

@tarcieri
Copy link
Member

@ixti what about on_event that takes a symbol (e.g. :error) as an argument?

@joshuaflanagan
Copy link
Contributor Author

@ixti what about on_event that takes a symbol (e.g. :error) as an argument?

I think that could be a good idea if you know of other events that would make sense to observe.
I could imagine having :request and :response events, which could replace the need to "wrap" those objects for all use cases. I understand the wrapping approach is required for some features, but it leads to an awkward implementation for things like logging, which don't need to modify the request/response.

@ixti
Copy link
Member

ixti commented Jul 24, 2019

Yeah. I think on_event makes sense to me.

And I agree, that :request and :response events will make notifications (which are actually observers) code look much better. Also after giving it another look, I guess I'm not very against on_error name any more, we can create a bunch of on_{event} methods:

def on_request(req:); end
def on_request_error(req:, err:); end
def on_response(res:); end
def on_response_error(res:, err:); end

So that it will be absolutely obvious which kwargs will be passed.

@joshuaflanagan
Copy link
Contributor Author

Can we move forward with this PR and leave the on_request/on_response changes for a follow-up effort?
I'm not exactly sure how you want to differentiate between on_request_error and on_response_error, but willing to make the changes with some direction.

@tarcieri
Copy link
Member

@joshuaflanagan that sounds fine to me

@joshuaflanagan
Copy link
Contributor Author

Done

@tarcieri
Copy link
Member

@joshuaflanagan this one now has a conflict

This addresses httprb#547

It allows a Feature to implement an on_error handler so that it has a chance to react to Requests that never get a Response.

> Extracted the build_response method to stay under the rubocop enforced method length limit.
@tarcieri
Copy link
Member

@ixti let me know if you have any qualms about landing this. We can potentially explore alternatives before cutting another release

@tarcieri tarcieri merged commit 609f07b into httprb:master Oct 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants