Timing out and retrying calls to third parties

By | | Ruby on Rails Tutorials & Articles

3

When calling third parties you want to set them a sensible timeout, and you also might want to make a few attempts before giving up. Here’s a relatively succinct way to accomplish this in Ruby (3 attempts, each with a timeout of 5 seconds):


3.times do
  begin
    Timeout::timeout(5) do
      # Call your third party (for a example, a payment gateway)
    end
    @success = true
    break
  rescue Exception
    # Try again!
  end
end
if @success
  # Jump for joy!
end

I’m sure somebody will chime in with an even sexier way…

Written By:

Tim Lucas

Tim (aka toolmantim) is a Sydney based, possum-eyed web application designer with a bent for web standards and user-centred design. When not hiding behind his camera he can be found doodling interface designs and coding Rails at his company aviditybytes.

 

{ 3 comments }

timlucas August 24, 2006 at 10:42 am

Fenrir2: nice abstraction of my code :)

myrdhrin: In my case I didn’t care watch was being thrown, but might be handier would be if you could pass in a array of exceptions to ignore.

retry_with_timeout(:ignoring => [Timeout::Error, SomeOtherError]) { ... }

There must be a way to make it sexier, say:

3.times { try_with_timeout(5.seconds, :ignoring => SomeOtherError) { ... } }

(the internal timeout should specify and catch its own timeout exception as well as SomeOtherError)

I’ll have a play this evening and see if I can whip that up.

myrdhrin August 24, 2006 at 6:48 am

Fenrir2, instead of catching all the exceptions would you not be better just to catch the Timeout::Error exception?

I mean, if the code in the yield really has a problem you want to know about it…

Fenrir2 August 24, 2006 at 4:53 am
def with_timeout(attempts = 3, timeout = 5)
  attempts.times do
    begin
      Timeout::timeout(timeout) do
        yield
      end
      return true
    rescue Exception
    end
  end
end

=>

with_timeout do
  # ...
end

Comments on this entry are closed.