jnunemaker / httparty

:tada: Makes http fun again!
MIT License
5.81k stars 964 forks source link

Configured timeout is duplicated #755

Closed carlosramone closed 2 years ago

carlosramone commented 2 years ago

As you can see, I configured 10 seconds of timeout. But it takes 20 seconds to throw the timeout exception.

require 'httparty'

class TimeoutHttparty
    include HTTParty

    default_timeout 10
    #open_timeout 1
    #read_timeout 10
    #write_timeout 1

    def test 
        puts('Start at: ' + Time.now.to_s)
        self.class.get("http://www.firebase.io")
        puts('End at: ' + Time.now.to_s)
    rescue StandardError => e
        puts('End with error at: ' + Time.now.to_s)
        puts e.message
    end
end

timeout = TimeoutHttparty.new
timeout.test

image

jnunemaker commented 2 years ago

Probably retrying either in httparty or in the level below automatically in net/http. Also read timeout can take longer because I think it's the time between bytes read so as long as a trickle of data is being read it can go longer.

jnunemaker commented 2 years ago

Closing to keep tidy but if you can show that this is httparty and not net/http or something else I'm happy to try to fix or merge pull request.

carlosramone commented 2 years ago

I'm not sure if it's httparty or net/http, but whatever timeout is set is doubled. I will keep checking.

Ruslan commented 2 years ago

This is net/http feature to retry requests

https://github.com/ruby/ruby/blob/v2_7_6/lib/net/http.rb#L762

it can be fixed in HTTParty like this:

Benchmark.measure { HTTParty.get('http://httpstat.us/200?sleep=50000&q=', timeout: 10) rescue nil } 
# @real=20.28650915599428,

Benchmark.measure { HTTParty.get('http://httpstat.us/200?sleep=50000&q=', timeout: 10, max_retries: 0) rescue nil } 
# @real=10.168669935999787,

So if you have time-limited workflow with blocking http GET requests, it's better to set max_retries to 0 to avoid our current request timeout. This is really dangerous hidden feature in some cases (some vendors have non-idempotent GET requests)