2011-06-28 74 views
3

我的應用程序控制器中有一個around_filter,用於封裝超時區塊中的所有操作,以便操作在達到30秒的Heroku限制之前失敗。我也有一個rescue_from Timeout :: Error來清理救援這些超時。不幸的是,rescue_from僅適用於某些時間。Rescue_from不救援視圖或幫助程序中的Timeout :: Error

如果在控制器內部執行時發生超時,但在視圖或幫助程序中發生超時時無法挽救,它可以正常工作。

無論是中斷還是SignalException,這兩種Timeout :: Error都繼承自正確的救援。然而,救援異常本身確實在視圖和助手內正確救援。

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

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

def timeout_rescue 
    # Rescued 
end 

是否有任何其他方法來解救Timeout :: Error以使其正常工作?

回答

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 

UPDATE

我修補的機架超時寶石正確返回超時::錯誤。這是一個線程問題。官方寶石已更新: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

太棒了,謝謝。這解決了我的問題! – Huston

+0

Huston,我最終修補了機架超時gem來解決問題。 Caio(kch)用補丁更新了正式的機架超時。 https://github.com/kch/rack-timeout – simple10

+1

對不起,以舊的線程。 。 。 。但我想知道如何在發生超時時使用上面的代碼正常關閉Postgres數據庫連接。我的應用程序「崩潰」,因爲機架超時發生,然後數據庫連接陷入僵局。 。 。那麼我所有的16個獨角獸進程都不能再連接到數據庫。我不確定這是否是一個全新的問題,因爲它似乎與這個問題有關。 – bcb

1

當Timeout需要引發異常終止執行時,它不會引發Timeout :: Error。如果是這樣,花園式的救援會陷入困境,而這不是你想要的。相反,它會引發自己的異常,它是從:: Exception中派生出來的,所以除了救援異常外,它還會通過任何救援。或者 - 您可以將自己的異常作爲第二個參數傳遞給Timeout :: timeout,並以這種方式解救它。請注意,超時將重新提高它。

閱讀timeout.rb代碼(在ruby200/lib/ruby​​/2.0.0中)。它很短,很有意思,會告訴你它是如何工作的。