3

すべてのアクションをタイムアウト ブロックに入れるために、アプリケーション コントローラーに around_filter を設定して、Heroku の 30 秒の制限に達する前にアクションが失敗するようにしています。これらのタイムアウトをきれいに救うために、rescue_from Timeout::Error もあります。残念ながら、rescue_from は時々しか機能しません。

コントローラー内で実行中にタイムアウトが発生した場合は問題なく動作しますが、ビューまたはヘルパー内でタイムアウトが発生した場合はレスキューに失敗します。

Timeout::Error の継承元である Interrupt も SignalException も、正しくレスキューしません。ただし、例外自体をレスキューすると、ビューとヘルパー内で正しくレスキューされます

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

2 に答える 2

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

アップデート

正しく Timeout::Error を返すように、rack-timeout gem にパッチを適用しました。それはスレッドの問題でした。公式の gem が更新されました: 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
于 2011-07-07T22:19:41.750 に答える
1

Timeout が実行を終了するために例外を発生させる必要がある場合、Timeout::Error は発生しません。もしそうなら、多種多様な救助はそれを捕まえるでしょう、そしてそれはあなたが望むものではありません. 代わりに、::Exception から派生した独自の Exception を発生させるため、rescue Exception を除くすべてのレスキューを吹き飛ばします。または - Timeout::timeout の 2 番目のパラメーターとして独自の Exception を渡すことができ、その方法でそれを救うことができます。Timeout はそれを再発生させることに注意してください。

timeout.rb コードを読みます (ruby200/lib/ruby/2.0.0 にあります)。それは非常に短く、非常に興味深いもので、実際にどのように機能するかを教えてくれます.

于 2013-11-16T04:36:25.557 に答える