Search code examples
ruby-on-railstimeoutrescue

Rescue_from doesn't rescue Timeout::Error from views or helpers


I have an around_filter in my application controller to encase all actions in a timeout block, so that actions fail before hitting the 30 second Heroku limit. I also have a rescue_from Timeout::Error to cleanly rescue these timeouts. Unfortunately, the rescue_from only works some of the time.

It works fine if the timeout occurs while executing within the controllers, but fails to rescue if the timeout happens within a view or a helper.

Neither Interrupt nor SignalException, both of which Timeout::Error inherits from, rescue correctly either. However, rescuing Exception itself does rescue correctly within views and helpers.

around_filter :timeout
rescue_from Timeout::Error, :with => :timeout_rescue

def timeout
  Timeout::timeout(10){
    yield 
  }
end

def timeout_rescue
  # Rescued
end

Is there any other way to rescue Timeout::Error to get this working?


Solution

  • I ran into the same problem. I'm using Rails 3 + Rack::Timeout and trying to rescue_from in ApplicationController.

    I ended up using this ...

    rescue_from Exception do |exception|
      if exception.is_a?(Timeout::Error) || /execution expired/ =~ exception.message
        # rescued from timeout error
      end
      raise
    end
    

    UPDATE

    I patched the rack-timeout gem to properly return Timeout::Error. It was a threading issue. Official gem has been updated: https://github.com/kch/rack-timeout

    The new preferred method is below. In general, it's not a great idea to rescue from Exception and should be avoided if possible.

    class ApplicationController < ActionController::Base
      rescue_from Timeout::Error, with: :handle_timeout
    
      def handle_timeout(exception)
        # handle timeout error
      end
    end