Rescue_from не спасает Timeout :: Ошибка от представлений или помощников - PullRequest
3 голосов
/ 28 июня 2011

У меня в контроллере приложения есть вокруг_фильтр, чтобы заключить все действия в блок тайм-аута, чтобы действия не выполнялись до достижения 30-секундного предела Heroku.У меня также есть rescue_from Timeout :: Error, чтобы чисто спасти эти таймауты.К сожалению, rescue_from работает только иногда.

Работает нормально, если тайм-аут происходит во время выполнения в контроллерах, но не удается спасти, если тайм-аут случается внутри представления или помощника.

Ни Interrupt, ни SignalException, оба из которых наследует Timeout :: Error, также не спасаются корректно.Однако, спасение самого 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 ]

4 голосов
/ 08 июля 2011

Я столкнулся с той же проблемой. Я использую Rails 3 + Rack :: Timeout и пытаюсь выполнить rescue_from в ApplicationController.

В итоге я использовал это ...

rescue_from Exception do |exception|
  if exception.is_a?(Timeout::Error) || /execution expired/ =~ exception.message
    # rescued from timeout error
  end
  raise
end

UPDATE

Я исправил драгоценный камень стойки, чтобы правильно вернуть Timeout :: Error. Это была проблема с потоками. Официальный драгоценный камень был обновлен: https://github.com/kch/rack-timeout

Новый предпочтительный метод приведен ниже. В общем, спасение от Исключения не очень хорошая идея, и ее следует избегать, если это возможно.

class ApplicationController < ActionController::Base
  rescue_from Timeout::Error, with: :handle_timeout

  def handle_timeout(exception)
    # handle timeout error
  end
end
1 голос
/ 16 ноября 2013

Когда Timeout необходимо вызвать исключение для прекращения выполнения, оно не вызывает Timeout :: Error.Если бы это было так, спасатели сорта огорода заманили бы его в ловушку, и это не то, что вы хотите.Вместо этого он создает свое собственное исключение, которое получено из :: Exception, поэтому он проходит через любое спасение, кроме спасательного исключения.Или - вы можете передать свое собственное исключение в качестве второго параметра Timeout :: timeout, и таким образом вы можете его спасти.Обратите внимание, что Timeout вызовет его заново.

Прочитайте код timeout.rb (в ruby200 / lib / ruby ​​/ 2.0.0).Он довольно короткий, довольно интересный и расскажет вам, как он на самом деле работает.

...