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

我怕爱的太早我们不能终老 提交于 2020-01-13 17:44:12

问题


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?


回答1:


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



回答2:


When Timeout needs to raise an exception to terminate execution, it does not raise Timeout::Error. If it did, garden-variety rescues would trap it, and that's not what you want. Instead, it raises its own Exception that is derived from ::Exception, so it blows through any rescue except for rescue Exception. Or - you can pass your own Exception as the second parameter to Timeout::timeout, and that way you can rescue it. Note that Timeout will re-raise it.

Read the timeout.rb code (in ruby200/lib/ruby/2.0.0). It's quite short, pretty interesting and will tell you how it really works.



来源:https://stackoverflow.com/questions/6501451/rescue-from-doesnt-rescue-timeouterror-from-views-or-helpers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!