Tuesday, May 28, 2013

Retrying things in ruby

Working with remote systems that are not always under your control often involves failures; I'm working on a system that does an API call on a remote system, and the remote system needs to call other systems to finish the call (it is calling a licensing server, from another company). The call already has timeouts and delays, but it crashes often enough, which requires me to restart the job (the job is inside a resque queue).

Now, if we try to do something, and it fails, it will usually raise an exception; Ruby has exception handling, including the rescue keyword, which will restart the block that started the exception; Ruby also has blocks, procs and lambdas, which allow us to pass a piece of code (OK, a closure :) to another function or method, so we can define a function as follows:
def retry_times(n, func)
n=n-1
return func.call()
rescue => e
puts "n=#{n} exception #{e}"
if n>0 then
retry
end
end
view raw retry_times.rb hosted with ❤ by GitHub

And then we could use it like:
retry_times(5,lambda{ || return 1/0;})
view raw retry1.rb hosted with ❤ by GitHub
Voila ! we now can easily retry our operation several times; if we wanted to be fancy, we could add a time to sleep between tries, and even define a small DSL for this, but for my needs this was enough.