Blog

Thoughts from my daily grind

Ruby `retry`- rerun a block of code on error

Posted by Ziyan Junaideen |Published: 02 January 2020 |Category: Ruby Language
Default Upload |

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.

Comments