I have an application running on Heroku that, on occasion, reports Timeout::Error and (ActionView::Template::Error) "execution expired".
This happens all over the website (i.e. not in a specific controller) so I would like to create a function that will handle these two errors, first by retrying two times and the redirect the user to a page that will tell them that the server is busy.
My current plan is to use the following in ApplicationController:
rescue_from Timeout::Error, :with => :rescue_from_timeout
def rescue_from_timeout
sleep 2
retry
end
but this will just loop and loop. I want it to break after two attempts. How can I do that?
Also, How can I handle ActionView::Template::Error for "execution expired"? I don't want to rescue all ActionView::Template::Error with retries, only the ones that provoke the "execution expired".
This is what my exception says:
[Exception] home#index (ActionView::Template::Error) "execution expired"
or
[Exception] calculations#result (ActionView::Template::Error) "Timeout::Error: execution expired
My question, thus: How can I handle these two types of errors by first retry twice and then throw an exception / redirect to error page?
Define this method:
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
And call with this:
retryable(:tries => 10, :on => Timeout::Error) do
your_code_here
end
You could put this in an around_filter in the application controller, that is the base class for all controllers in a rails application:
class ApplicationController < ActionController::Base
around_filter :retry_on_timeout
def retry_on_timeout
retryable(:tries => 10, :on => Timeout::Error) do
yield
end
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With