我的应用程序控制器中有一个around_filter来封装超时块中的所有操作,因此在达到30秒Heroku限制之前操作失败。我还有一个来自Timeout :: Error的rescue_来干净地拯救这些超时。不幸的是,rescue_from只在某些时候有效。
如果在控制器内执行时发生超时,它可以正常工作,但如果在视图或帮助器中发生超时则无法解决。
Interrupt :: Error继承的Interrupt和SignalException都没有正确地进行救援。但是,拯救Exception本身会在视图和帮助程序中正确地进行救援。
around_filter :timeout
rescue_from Timeout::Error, :with => :timeout_rescue
def timeout
Timeout::timeout(10){
yield
}
end
def timeout_rescue
# Rescued
end
还有其他方法来拯救Timeout :: Error以使其正常工作吗?
答案 0 :(得分:4)
我遇到了同样的问题。我正在使用Rails 3 + Rack :: Timeout并尝试在ApplicationController中进行rescue_from。
我最终使用了这个...
rescue_from Exception do |exception|
if exception.is_a?(Timeout::Error) || /execution expired/ =~ exception.message
# rescued from timeout error
end
raise
end
<强>更新强>
我修补了rack-timeout gem以正确返回Timeout :: Error。这是一个线程问题。官方宝石已更新:https://github.com/kch/rack-timeout
新的首选方法如下。一般来说,从Exception中拯救并不是一个好主意,如果可能的话应该避免。
class ApplicationController < ActionController::Base
rescue_from Timeout::Error, with: :handle_timeout
def handle_timeout(exception)
# handle timeout error
end
end
答案 1 :(得分:1)
当Timeout需要引发异常以终止执行时,它不会引发Timeout :: Error。如果确实如此,花园式的救援将陷入其中,而这不是你想要的。相反,它引发了自己的Exception,它派生自:: Exception,因此除了救援Exception之外,它还会受到任何救援。或者 - 你可以将自己的Exception作为第二个参数传递给Timeout :: timeout,这样你就可以拯救它。请注意,Timeout会重新提升它。
读取timeout.rb代码(在ruby200 / lib / ruby / 2.0.0中)。它很短,很有趣,会告诉你它是如何运作的。