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
    Timeout::timeout(5) do
      # Call your third party (for a example, a payment gateway)
    @success = true
  rescue Exception
    # Try again!

if @success
  # Jump for joy!

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

Get your free chapter of Level Up Your Web Apps with Go

Get a free chapter of Level Up Your Web Apps with Go, plus updates and exclusive offers from SitePoint.

  • Fenrir2
    def with_timeout(attempts = 3, timeout = 5)
      attempts.times do
          Timeout::timeout(timeout) do
          return true
        rescue Exception


    with_timeout do
      # ...
  • myrdhrin

    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…

  • http://www.toolmantim.com timlucas

    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.

Related books & courses
Available now on SitePoint Premium

Preview for $1