Rescue_from不会从视图或帮助程序中解救Timeout :: Error

时间:2011-06-28 04:13:03

标签: ruby-on-rails timeout rescue

我的应用程序控制器中有一个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以使其正常工作吗?

2 个答案:

答案 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中)。它很短,很有趣,会告诉你它是如何运作的。

相关问题