Обработка TimeOut :: Ошибка с повтором - PullRequest
7 голосов
/ 26 января 2012

У меня есть приложение, работающее на Heroku, которое иногда сообщает Timeout :: Error и (ActionView :: Template :: Error) "истек срок выполнения" .

Это происходит по всему сайту (т.е. не в конкретном контроллере), поэтому я хотел бы создать функцию, которая будет обрабатывать эти две ошибки, сначала повторив попытку дважды и перенаправив пользователя на страницу, которая сообщит им, что сервер занят.

Мой текущий план заключается в использовании следующего в ApplicationController:

  rescue_from Timeout::Error, :with => :rescue_from_timeout

  def rescue_from_timeout
    sleep 2
    retry 
  end

но это будет просто цикл и цикл. Я хочу, чтобы это сломалось после двух попыток. Как я могу это сделать?

Кроме того, как я могу обработать ActionView :: Template :: Error для "expired expired"? Я не хочу спасать все ActionView :: Template :: Error с повторными попытками, только те, которые провоцируют «истек срок выполнения».

Вот что говорит мое исключение:

[Exception] home#index (ActionView::Template::Error) "execution expired"

или

[Exception] calculations#result (ActionView::Template::Error) "Timeout::Error: execution expired

Мой вопрос, таким образом: как я могу обработать эти два типа ошибок, сначала повторив попытку дважды, а затем выдав исключение / перенаправление на страницу ошибки?

1 Ответ

15 голосов
/ 26 января 2012

Определите этот метод:

def retryable(options = {})
  opts = { :tries => 1, :on => Exception }.merge(options)

  retry_exception, retries = opts[:on], opts[:tries]

  begin
    return yield
  rescue retry_exception
    if (retries -= 1) > 0
      sleep 2
      retry 
    else
      raise
    end
  end
end

И позвоните с этим:

retryable(:tries => 10, :on => Timeout::Error) do
  your_code_here
end

Вы можете поместить это в around_filter в контроллере приложения, который является базовым классом для всех контроллеров в приложении rails:

class ApplicationController < ActionController::Base

  around_filter :retry_on_timeout

  def retry_on_timeout
    retryable(:tries =>  10, :on => Timeout::Error) do
      yield
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...