Ruby: Difference Between Read_Timeout and Open_Timeout

What is the difference between timeout and open timeout?

You're reading the wrong documentation (yours is for wgibbs-rest-client which has not been updated since 2009): here's the right one. But that one does not say anything about the difference either, although it is simple:

:open_timeout is the timeout for opening the connection. This is useful if you are calling servers with slow or shaky response times.

:timeout is the timeout for reading the answer. This is useful to make sure you will not get stuck half way in the reading process, or get stuck reading a 5 MB file when you're expecting 5 KB of JSON.

What is timeout and open timeout in Faraday?

If you look at the source code at https://github.com/lostisland/faraday/blob/master/lib/faraday/request.rb then you'll see:

#   :timeout      - open/read timeout Integer in seconds
# :open_timeout - read timeout Integer in seconds

Not very helpful, perhaps? Well, if you look at Faraday's Net::HTTP adapter at https://github.com/lostisland/faraday/blob/master/lib/faraday/adapter/net_http.rb, you'll see:

http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
http.open_timeout = req[:open_timeout] if req[:open_timeout]

So Faraday's open_timeout is equivalent to Net::HTTP's open_timeout which is documented as:

Number of seconds to wait for the connection to open. Any number may be used, including Floats for fractional seconds. If the HTTP object cannot open a connection in this many seconds, it raises a TimeoutError exception.

And Faraday's timeout is equivalent to Net::HTTP's read_timeout which is documented as:

Number of seconds to wait for one block to be read (via one read(2) call). Any number may be used, including Floats for fractional seconds. If the HTTP object cannot read data in this many seconds, it raises a TimeoutError exception.

If Net::HTTP's open_timeout and read_timeout are not set, will it wait indefinitely?

This actually means that server exists and accepts the request, but doesn’t return data, still keeping a connection open. Yes, in a case of such a malicious server the client will hang up.

There is no default timeout in Net::HTTP. In normal scenario it will receive HTTPRequestTimeOut response (which server is on duty of.) If you feel there might be any problem, you set the timeout yourself. But sometimes you really need to wait infinitely (server is processing large amount of data and you know it.)

Actually, I’d suggest it’s not a Net::HTTP problem. Matz has already had problems with rb_wait_for_single_fd calls. It actually looks like deadlock inside ruby thread synching, not like a server hangup.

How to tell a connect timeout error from a read timeout error in Ruby's Net::HTTP

Here's the solution (after Ben's fix):

require "net/http"
http = Net::HTTP.new("example.com")
http.open_timeout = 2
http.read_timeout = 3
begin
http.start
begin
http.request_get("/whatever?") do |res|
res.read_body
end
rescue Timeout::Error
puts "Timeout due to reading"
end
rescue Timeout::Error
puts "Timeout due to connecting"
end

How is Ruby TCPSocket timeout defined?

Use begin .. rescue Errno::ETIMEDOUT to catch the timeout:

require 'socket'

begin
TCPSocket.new('www.example.com', 111)
rescue Errno::ETIMEDOUT
p 'timeout'
end

To catch any socket exceptions, use SystemCallError instead.

According to the SystemCallError documentation:

SystemCallError is the base class for all low-level platform-dependent errors.

The errors available on the current platform are subclasses of
SystemCallError and are defined in the Errno module.


TCPSocket.new does not support timeout directly.

Use Socket::connect_non_blocking and IO::select to set timeout.

require 'socket'

def connect(host, port, timeout = 5)

# Convert the passed host into structures the non-blocking calls
# can deal with
addr = Socket.getaddrinfo(host, nil)
sockaddr = Socket.pack_sockaddr_in(port, addr[0][4])

Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0).tap do |socket|
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)

begin
# Initiate the socket connection in the background. If it doesn't fail
# immediatelyit will raise an IO::WaitWritable (Errno::EINPROGRESS)
# indicating the connection is in progress.
socket.connect_nonblock(sockaddr)

rescue IO::WaitWritable
# IO.select will block until the socket is writable or the timeout
# is exceeded - whichever comes first.
if IO.select(nil, [socket], nil, timeout)
begin
# Verify there is now a good connection
socket.connect_nonblock(sockaddr)
rescue Errno::EISCONN
# Good news everybody, the socket is connected!
rescue
# An unexpected exception was raised - the connection is no good.
socket.close
raise
end
else
# IO.select returns nil when the socket is not ready before timeout
# seconds have elapsed
socket.close
raise "Connection timeout"
end
end
end
end

connect('www.example.com', 111, 2)

The above code comes from "Setting a Socket Connection Timeout in Ruby".

Rollbar Error processing the item: Net::OpenTimeout, execution expired

I have found the way to make it work. My final configuration is

  Rollbar.reconfigure do |config|
config.access_token = ENV['ROLLBAR_TOKEN']
config.open_timeout = 15
config.request_timeout = 15

if %w(test development).include?(Rails.env)
config.enabled = false
end
end

the trick is to use reconfigure instead of configure otherwise it will not override the timeouts!



Related Topics



Leave a reply



Submit