2012-01-26 10 views
7

Tengo una aplicación que se ejecuta en Heroku que, en ocasiones, los informes de Tiempo de espera :: error y (ActionView :: :: Plantilla de error) "ejecución caducado".manija tiempo de espera :: Error con reintento

Esto ocurre en todo el sitio web (es decir, no en un controlador específico) así que me gustaría crear una función que manejará estos dos errores, primero volviendo a intentar dos veces y redirigir al usuario a una página que les dirá que el servidor está ocupado

Mi plan actual es utilizar el siguiente en ApplicationController:

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

    def rescue_from_timeout 
    sleep 2 
    retry 
    end 

pero esto acaba de bucle y bucle. Quiero que se rompa después de dos intentos. ¿Cómo puedo hacer eso?

Además, ¿cómo puedo manejar ActionView :: Template :: Error para "ejecución expirada"? No quiero rescatar todo ActionView :: Template :: Error con reintentos, solo los que provocan la "expiración de la ejecución".

Esto es lo que mi excepción dice:

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

o

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

Mi pregunta, por lo tanto: ¿Cómo puedo manejar estos dos tipos de errores de primer reintento dos veces y luego una excepción/redirigir a la página de error?

+1

¿Por qué se plantea esta excepción? ¿Ha implementado algún tipo de tareas de larga ejecución? ¿Depende su aplicación de un servicio web externo? – Jef

Respuesta

15

definir este método:

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 

y llame con esto:

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

se puede poner esto en un around_filter en el controlador de aplicación, que es la clase base para todos los controladores en un raíles aplicación:

class ApplicationController < ActionController::Base 

    around_filter :retry_on_timeout 

    def retry_on_timeout 
    retryable(:tries => 10, :on => Timeout::Error) do 
     yield 
    end 
    end 
end 
+1

Gracias, Douglas. Sin embargo, no estoy seguro de dónde/cómo usar el código de llamada. Si quiero usarlo para que capte este error en todo el sitio web, supongo que tendría algo llamado en el controlador de la aplicación como un filtro anterior o algo así. ¿Debo ajustar cada controlador, etc., con la función de recuperación? ¿Podría explicar cómo puedo usar esto para detectar el error en todo el sitio web (todos los controladores/vistas)? – Christoffer

+0

Edité la respuesta usando un filtro de alrededor en ApplicationController. Esto aplica para usted? –

+0

No puedo probarlo más que manteniéndolo en línea durante unos días y ver si elimina estos mensajes de error, pero parece estar funcionando. O bien, ¿hay alguna manera de provocar un TimeoutError para poder probarlo? – Christoffer

Cuestiones relacionadas