tags:

views:

195

answers:

1

My question is related to http://stackoverflow.com/questions/2370140/how-to-rescue-timeout-issues-ruby-rails.

Here's the common way to rescue from a timeout:

def action
  # Post using Net::HTTP
rescue Timeout::Error => e
  # Do something
end

I'd like to determine if the exception was raised while trying to connect to the host, or if it was raised while trying to read from the host. Is this possible?

A: 

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
Marc-André Lafortune
Marc, I really want this to be true, but it's not working for me. I think it's because `http.request_get` creates and uses a new instance of `Net::HTTP` that doesn't inherit the timeout variables.
Ben Marini
I take that back, it doesn't create a new instance of `Net:HTTP`. Still, it seems to timeout around 30 seconds no matter what I set the open and read timeouts to.
Ben Marini
open_timeout works for me, on both ruby 1.8.7 and 1.9.2 dev. It's harder to test read_timeout, and it might be per block read, you should check the code. Still, if you put both to 0.1, it should timeout quickly, no?In any case, my answer is still the valid way to distinguish what caused the timeout!
Marc-André Lafortune
Figured it out. I was testing with "blah.com", which has no DNS entry. The code above doesn't catch a timeout due to resolution failure for some reason. Your code works perfectly with a small modification. You have to put `request_get` inside the inner rescue block, and add a call to `http.start` in the outer rescue block, like this: http://gist.github.com/364868Update your answer and I'll accept it. Thanks so much Marc!
Ben Marini
Ah, good, and sorry for not getting it quite right. I updated the answer with your modification.
Marc-André Lafortune