Friday, July 9, 2010

Retry on Exception

I got this little snippet from this website,
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

If I modify this just a little bit, I can avoid the double yield while retrying and eventually failing. Here's the modified version:
def do_it_over_again(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
    raise opts[:on]
  end
end

Notice that I raise the exception we're trying to avoid instead of yielding one more time than we expect it to.

Now, instead of this:
jruby-1.5.1 > do_it_over_again(:tries => 5, :on => CustomExceptions::RejectedLoginException) do
  puts "hey" 
  raise CustomExceptions::RejectedLoginException
end
hey
hey
hey
hey
hey
hey
CustomExceptions::RejectedLoginException: CustomExceptions::RejectedLoginException
 from (irb):28


I get this:
jruby-1.5.1 > do_it_over_again(:tries => 5, :on => CustomExceptions::RejectedLoginException) do 
  puts "hey"
  raise CustomExceptions::RejectedLoginException
end
hey
hey
hey
hey
hey
CustomExceptions::RejectedLoginException: CustomExceptions::RejectedLoginException
 from (irb):10:in `do_it_over_again'
 from (irb):17

Notice that it runs only five times in the modified code instead of six. It's definitely worth it to check out that post though, so go ahead..

No comments:

Post a Comment