-
Notifications
You must be signed in to change notification settings - Fork 322
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
Simplify setting a timeout #446
Conversation
RuboCop errors:
|
When I read #444, I imagined that specifying an integer would mean having a timeout around the whole request, in a way that the request can time out during any operation, not just read. With the currently proposed implementation the request can take longer than |
Indeed, I forgot to divide by 3. Global timeout doesn't work in the least surprising way, IMO. |
hrm. maybe setting only one to the expected global value will work as expected? http/lib/http/timeout/global.rb Line 20 in 70658da
In my apps, I've been setting all three of those to a third of my total time allowed. I'm thinking just setting one will do the trick. |
be95b24
to
873efbf
Compare
Sorry about this, it's mostly a wart from how I implemented it a few years ago. You can add a new field like |
I know we're at 3.0.0 now, but it might be nice to go to 4.0.0 and redesign the timeout API a bit. That would definitely simplify moving things over to Socketry underneath |
98461eb
to
99380ab
Compare
I created a I don't like that the deprecation warning requires using the connection, I would have liked to make |
@mikegee I'd suggest (based on the feedback above) rewriting the patch without regard to backwards compatibility |
@tarcieri alrighty. I'm working on it. |
1238cec
to
0cb3f69
Compare
I updated the title and description of this change. I would appreciate some review now. |
lib/http/timeout/global.rb
Outdated
end | ||
|
||
# To future me: Don't remove this again, past you was smarter. | ||
def reset_counter | ||
@time_left = connect_timeout + read_timeout + write_timeout | ||
@total_timeout = time_left | ||
@time_left = timeout |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personal flavor, but can you please use instance variable instead of attr reader here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, sure. I'll change PerOperation
to match your preferred style, too.
BTW, I avoid instance variables in my code since typos can lead to subtle bugs: @mispelled #=> nil
, whereas misspelled method calls raise a NameError
.
lib/http/timeout/global.rb
Outdated
@@ -124,7 +126,7 @@ def reset_timer | |||
def log_time | |||
@time_left -= (Time.now - @started) | |||
if time_left <= 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. I know that it was before, but please update this one too to use instance variable instead.
lib/http/chainable.rb
Outdated
# Adds a global timeout to the full request | ||
# @param [Numeric] global_timeout | ||
def timeout(options, extra_arg = nil) | ||
raise ArgumentError, TIMEOUT_USAGE if extra_arg |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is gonna be a breaking change, so I think it's fine to just change method signature to accept single argument only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I debated this, but thought a bit of effort to ease the transition was worth it. I'll remove it. No worries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per #447 we might end up redoing the whole thing with keyword arguments anyway, but don't worry about that for this PR
Couple of changes - and I will be glad to merge it. |
Looks good to me too... aside from @ixti's nits |
These were too noisy for me: WARNING: Using the `raise_error` matcher without providing a specific error or message risks false positives, since `raise_error` will match when Ruby raises a `NoMethodError`, `NameError` or `ArgumentError`, potentially allowing the expectation to pass without even executing the method you are intending to call. Actual error raised was #<NoMethodError: undefined method `fetch' for "[FOOBAR]":String>. Instead consider providing a specific error class or message. This message can be suppressed by setting: `RSpec::Expectations.configuration.on_potential_false_positives = :nothing`. Called from /home/travis/build/httprb/http/spec/lib/http_spec.rb:252:in `block (3 levels) in <top (required)>'. WARNING: Using the `raise_error` matcher without providing a specific error or message risks false positives, since `raise_error` will match when Ruby raises a `NoMethodError`, `NameError` or `ArgumentError`, potentially allowing the expectation to pass without even executing the method you are intending to call. Actual error raised was #<KeyError: key not found: :user>. Instead consider providing a specific error class or message. This message can be suppressed by setting: `RSpec::Expectations.configuration.on_potential_false_positives = :nothing`. Called from /home/travis/build/httprb/http/spec/lib/http_spec.rb:260:in `block (3 levels) in <top (required)>'. WARNING: Using the `raise_error` matcher without providing a specific error or message risks false positives, since `raise_error` will match when Ruby raises a `NoMethodError`, `NameError` or `ArgumentError`, potentially allowing the expectation to pass without even executing the method you are intending to call. Actual error raised was #<KeyError: key not found: :pass>. Instead consider providing a specific error class or message. This message can be suppressed by setting: `RSpec::Expectations.configuration.on_potential_false_positives = :nothing`. Called from /home/travis/build/httprb/http/spec/lib/http_spec.rb:256:in `block (3 levels) in <top (required)>'.
- `.timeout(<Numeric>)` sets a global timeout value. - `.timeout(connect: x, write: y, read: z)` sets per operation timeouts. The previous style: `.timeout(:global|:per_operation, hash_of_options)` doesn't work anymore.
8ec5597
to
11e1580
Compare
I don't understand the build failure. It is in unrelated code, I can't duplicate it locally in 2.4.1, and when I pushed a commit focused on that spec, it passed. Is there a way to tell Travis to retry? |
Yeah, I have restarted. |
end | ||
|
||
it "fails when :user is not given" do | ||
expect { HTTP.basic_auth :pass => "[PASS]" }.to raise_error | ||
expect { HTTP.basic_auth :pass => "[PASS]" }.to raise_error(KeyError) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huge thanks for fixing those!
Thank you for your contribution! |
Thanks! |
Update ruby-http to 4.4.1. ## 4.4.1 (2020-03-29) * Backport [#590](httprb/http#590) Fix parser failing on some edge cases. ([@ixti]) ## 4.4.0 (2020-03-25) * Backport [#587](httprb/http#587) Fix redirections when server responds with multiple Location headers. ([@ixti]) * Backport [#599](httprb/http#599) Allow passing HTTP::FormData::{Multipart,UrlEncoded} object directly. ([@ixti]) ## 4.3.0 (2020-01-09) * Backport [#581](httprb/http#581) Add Ruby-2.7 compatibility. ([@ixti], [@janko]) ## 4.2.0 (2019-10-22) * Backport [#489](httprb/http#489) Fix HTTP parser. ([@ixti], [@fxposter]) ## 4.1.1 (2019-03-12) * Add `HTTP::Headers::ACCEPT_ENCODING` constant. ([@ixti]) ## 4.1.0 (2019-03-11) * [#533](httprb/http#533) Add URI normalizer feature that allows to swap default URI normalizer. ([@mamoonraja]) ## 4.0.5 (2019-02-15) * Backport [#532](httprb/http#532) from master. Fix pipes support in request bodies. ([@ixti]) ## 4.0.4 (2019-02-12) * Backport [#506](httprb/http#506) from master. Skip auto-deflate when there is no body. ([@Bonias]) ## 4.0.3 (2019-01-18) * Fix missing URL in response wrapped by auto inflate. ([@ixti]) * Provide `HTTP::Request#inspect` method for debugging purposes. ([@ixti]) ## 4.0.2 (2019-01-15) * [#506](httprb/http#506) Fix instrumentation feature. ([@paul]) ## 4.0.1 (2019-01-14) * [#515](httprb/http#515) Fix `#build_request` and `#request` to respect default options. ([@RickCSong]) ## 4.0.0 (2018-10-15) * [#482](httprb/http#482) [#499](httprb/http#499) Introduce new features injection API with 2 new feaures: instrumentation (compatible with ActiveSupport::Notification) and logging. ([@paul]) * [#473](httprb/http#473) Handle early responses. ([@janko-m]) * [#468](httprb/http#468) Rewind `HTTP::Request::Body#source` once `#each` is complete. ([@ixti]) * [#467](httprb/http#467) Drop Ruby 2.2 support. ([@ixti]) * [#436](httprb/http#436) Raise ConnectionError when writing to socket fails. ([@janko-m]) * [#438](httprb/http#438) Expose `HTTP::Request::Body#source`. ([@janko-m]) * [#446](httprb/http#446) Simplify setting a timeout. ([@mikegee]) * [#451](httprb/http#451) Reduce memory usage when reading response body. ([@janko-m]) * [#458](httprb/http#458) Extract HTTP::Client#build_request method. ([@tycoon]) * [#462](httprb/http#462) Fix HTTP::Request#headline to allow two leading slashes in path. ([@scarfacedeb]) * [#454](httprb/http#454) [#464](httprb/http#464) [#384](httprb/http#384) Fix #readpartial not respecting max length argument. ([@janko-m], [@marshall-lee])
Since http-rb 4.0, the http-rb gem has supported a better global timeout as `timeout(seconds)`. httprb/http#446 As the [http-rb wiki explains](https://github.com/httprb/http/wiki/Timeouts), using eg `timeout(3)` means that 3 seconds is an upper bound for the entire HTTP call. The old way of doing things, before this PR, setting a faraday `timeout` value of `3` would turn into `HTTP.timeout(connect: 3, write: 3, read: 3)`, which would mean the whole HTTP call could actually take up to **9** seconds: 3 for open, 3 for write, another 3 for read. The new way is better semantics for a single faraday `timeout` option. It's been supported since http-rb 4.0, and this Faraday adapter doesn't support any earlier http-rb. It makes sense to change to use the new better way. The existing functionality is not tested here; and I couldn't figure out any good way to test it. Mocking http-rb raising a timeout error would _not_ test this functionality of passing in timeout confiuration appropriately to http-rb. I spent some time on it, but couldn't figure out any good way to test, sorry. This is not a reduction in test coverage, it already wasn't tested.
As of httprb/http#446 Increasing the http dependancy to `4.0` where this change is released.
As of httprb/http#446 Increasing the http dependancy to `4.0` where this change is released.
.timeout(<Numeric>)
sets a global timeout value..timeout(connect: x, write: y, read: z)
sets per operation timeouts.The previous style:
.timeout(:global|:per_operation, hash_of_options)
doesn't work anymore.fixes #444