Ruby Idiom To Retry open() Upto N Times Before Giving Up

I write a lot of scripts that I run once or infrequently that uses
open-rui. Occasionally I run into a web site that times out or is
unavailable for a period of time. My normal solution is to just rerun
the script manually at a later time and the problem goes away. What I
would like to start doing is rescuing the open() and retrying the open()
after a delay. What would be the most idiomatic way to try opening a url
say n times before giving up? Here is my crude code for trying twice:

beginÂ
  open(“http://www.example.com/foo.html”)
 rescueÂ
  beginÂ
     open(“http://www.example.com/foo.html”)
   rescueÂ
     #tried twice - giving upÂ
  endÂ
endÂ

I would like a more general approach using ruby idioms where I could
specify the maximum number of attempts and delay before giving up.
Thanks for your help.

On 22.02.2010 19:53, Dan wrote:

end

I would like a more general approach using ruby idioms where I could specify the maximum number of attempts and delay before giving up. Thanks for your help.

You can use “retry”:

irb(main):017:0> attempts = 3
=> 3
irb(main):018:0> begin
irb(main):019:1* raise “Error, attempt = #{attempts}”
irb(main):020:1> rescue => e
irb(main):021:1> puts e
irb(main):022:1> attempts -= 1
irb(main):023:1> retry if attempts > 0
irb(main):024:1> puts “giving up”
irb(main):025:1> end
Error, attempt = 3
Error, attempt = 2
Error, attempt = 1
giving up
=> nil
irb(main):026:0>

Kind regards

robert

On Mon, Feb 22, 2010 at 11:53 AM, Dan [email protected] wrote:

end

Use ‘retry’.

This is a simple sketch of the concept:

irb(main):001:0> n = 0
=> 0
irb(main):002:0> begin
irb(main):003:1* raise “#{n} tries”
irb(main):004:1> rescue
irb(main):005:1> n += 1
irb(main):006:1> retry unless n == 3
irb(main):007:1> raise
irb(main):008:1> end
RuntimeError: 2 tries
from (irb):3
from :0

Kirk H.

On Mon, Feb 22, 2010 at 12:53, Dan [email protected] wrote:

I would like a more general approach using ruby idioms where I could specify the maximum number of attempts and delay before giving up. Thanks for your help.

Something along the lines of:

def open_with_retry(url, n=10, delay=1)
1.upto(n) do
begin
open(url) do |handle|
yield handle
end
break
rescue
puts “Sleeping …”
sleep delay
end
end
end

open_with_retry(‘http://does.not.resolve.tld/’, 5, 2) do |h|
puts “Doing something with #{h.inspect}”
end

Note that this sleeps even if the last attempt failed.

Marcelo

On Feb 22, 11:53 am, Dan [email protected] wrote:

end

I would like a more general approach using ruby idioms where I could specify the maximum number of attempts and delay before giving up. Thanks for your help.

gem install attempt

Try twice, 10 seconds apart

attempt(2, 10){
open(‘http://www.example.com/foo.html’)
}

Regards,

Dan

On Mon, Feb 22, 2010 at 1:53 PM, Dan [email protected] wrote:

end

I would like a more general approach using ruby idioms where I could specify the maximum number of attempts and delay before giving up. Thanks for your help.

begin
raise “oops”
rescue
retry_count = (retry_count || 0) + 1
puts “retry #{retry_count}”
retry unless retry_count >= 5
end


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: Rick DeNatale - Developer - IBM | LinkedIn

attempt() looks actually pretty cool.

Wonder if it would support this as well :smiley:

attempt(“twice”, “10 minutes”){
open(‘http://www.example.com/foo.html’)
}

hehe :smiley:

Dan wrote:

end

I would like a more general approach using ruby idioms where I could specify the maximum number of attempts and delay before giving up. Thanks for your help.

Another approach (minus the delay part):

$ cat open-with-retry.rb
def open_with_retry uri, tries=3
catch :success do
tries.times do |i|
begin
throw :success, open(uri)
rescue => e
puts “try ##{i}: #{e}”
end
end
raise “Giving up”
end
end

f = open_with_retry(ARGV[0])
puts f.read

$ ruby open-with-retry.rb readme.txt
this is a file

$ ruby open-with-retry.rb noexist
try #0: No such file or directory - noexist
try #1: No such file or directory - noexist
try #2: No such file or directory - noexist
open-with-retry.rb:10:in open_with_retry': Giving up (RuntimeError) from open-with-retry.rb:2:incatch’
from open-with-retry.rb:2:in `open_with_retry’
from open-with-retry.rb:14