Ruby `retry`- rerun a block of code on error
Handling errors, especially in edge cases, is essential in any program. The retry
method in Ruby is helpful when we need to rerun a block of code when there is an error.
Basic usage
begin
# Code to execute that may raise an error
rescue
# The following `retry` will execute the code block between `begin` & `rescue`
retry
end
The above code snippet is not exactly a great example. As you can see, this code may run indefinitely. Ideally, we may only want to repeat this code n times before giving up. When we are giving up, we may need to re-raise the error so that an error tracking platform like Rollabr will register the mistake.
A practical example
# Process a payment in a repeatable fashion and log errors
# @since 1.0.0
# @note Retry method introduced since 1.182.0 (ref: GF-319)
# @example
# gateway = PyamentGateways::USAePay.new(options)
# gateway.process_payment
# @return [GatewayResponse] the response from the gateway
def process_payment
attempts ||= 1
charge_customer
rescue => error
attempts += 1
if attempts <= 3
sleep 2.seconds
retry
end
ErrorMonitor.record(:gateway_retry_exceeded, error: error, debug: debug)
raise
end
# Charges the payment method (CC or ACH)
# @return [GatewayResponse] the gateway response
def charge_customer
# API call that may occasionally raise an error
end
The application attempts to charge a customer by making an API request to the payment gateway. 99.999% of the time, this request goes through without incident. But there are times when we encounter an error.
Here I am recording the number of attempts to a variable named attempts
and incrementing it gradually. When it reaches a defined boundary condition I stop retrying. Then I record the error to an internal error monitoring service ErrorMonitor
(you may use Rollbar
) and re-raise
the error so that the next layer can handle the exception as it sees fits.
History
I have used the retry
method since Ruby 1.8. In Ruby 1.8, the retry
method (along with redo
) would restart a loop's iteration. This behaviour changed since Ruby 1.9, where the retry
method was restricted to exception handling (begin
/rescue
). Since the redo
method is only available within loops.
About the Author
Ziyan Junaideen -
Ziyan is an expert Ruby on Rails web developer with 8 years of experience specializing in SaaS applications. He spends his free time he writes blogs, drawing on his iPad, shoots photos.