Ruby, Rails, Firefox, Anime, Mac
In: Ruby
14 Jan 2008I am not certain whether the ability to retry a code block when encountering exceptions was a feature available in Ruby, but I certainly couldn’t find anything on that topic (what I did find were mostly about the retry
keyword for iterator loops).
Before you ask why I need this, the motivation for this was because I was getting intermittent HTTP errors (503s mostly) trying to connect to a web service. Turns out it’s really easy in Ruby to implement a retryable
method that does something like this:
retryable(:tries => 5, :on => OpenURI::HTTPError) do
open('http://example.com/flaky_api')
# Code that mashes up stuff for your "social networking" site.
end
Here are the Kernel#retryable specs (pastie).
And the code:
# Options:
# * :tries - Number of retries to perform. Defaults to 1.
# * :on - The Exception on which a retry will be performed. Defaults to Exception, which retries on any Exception.
#
# Example
# =======
# retryable(:tries => 1, :on => OpenURI::HTTPError) do
# # your code here
# end
#
def retryable(options = {}, &block)
opts = { :tries => 1, :on => Exception }.merge(options)
retry_exception, retries = opts[:on], opts[:tries]
begin
return yield
rescue retry_exception
retry if (retries -= 1) > 0
end
yield
end
It’s not hard to implement the same for checking return values as well, i.e.
retryable_deluxe(:tries => 5, :on => { :return => nil }) { puts "working..." }
retryable_deluxe(:on => { :exception => StandardError, :return => nil }) do
# your code here
end
Ruby is nice.
11 Responses to Retrying code blocks in Ruby (on exceptions, whatever)
rubylicio.us
January 14th, 2008 at 8pm
Good idea and nice little snippet, I usually tend to skip conditional retries, for no better reason then it feels like it clutters up my code alot … which is a somewhat lame reason now that I think about it :)
Wonder if this could be built into “retry” itself somehow ..
rubylicio.us
January 14th, 2008 at 8pm
I ofcourse meant built into “rescue”, not “retry” in the above post.
Chu Yeow
January 14th, 2008 at 8pm
Yup exactly – I hated having to put conditionals in there for retries. Thankfully for Ruby blocks, we can abstract that considerably :)
That sounds really nice, if we could monkey patch
rescue
, but I think it could be hard sincerescue
‘s a language keyword.macournoyer
January 14th, 2008 at 10pm
very nice, I like your retryable method!
Geoff Buesing
January 15th, 2008 at 1am
I like this idea.
I think you could avoid the double yield in your implementation by using Ruby’s “retry” method:
rescue SomeError
tries -= 1
retry if tries > 0
Jeremy McAnally
January 15th, 2008 at 2am
The retry keyword works for exceptions also. You could easily write a little helper to handle the retry counter, etc.
Chu Yeow
January 15th, 2008 at 9am
You’re right, Geoff and Jeremy! I wasn’t aware the retry keyword worked for exceptions as well. I’ve updated the code :).
www.hans-eric.com » Blog Archive » Loop Abstractions in D
January 18th, 2008 at 5am
[…] with Ruby is the natural way in which you can hide looping constructs with descriptive names. Like the retryable example that Cheah Chu Yeow gives on his […]
Loop Abstractions in D revisited
January 31st, 2008 at 11pm
[…] I showed you how we could make loop constructs abstract, in a similar way which is common in Ruby. The example I used as a model was the retryable method from Cheah Chu Yeow. His version is customizable in a way that let you […]
A Ruby ‘tries’ method # Another code blog
October 15th, 2009 at 11am
[…] exercise. Tj Holowaychuk posted a retry method, which appears itself to be a refactoring of the retryable […]
Trevor Turk — Links for 12-3-10
December 4th, 2010 at 7am
[…] Retrying code blocks in Ruby (on exceptions, whatever) Before you ask why I need this, the motivation for this was because I was getting intermittent HTTP errors (503s mostly) trying to connect to a web service. […]