From: Robert Klemme Date: 2013-01-25T02:55:07+09:00 Subject: Re: How to DRY this up? On Thu, Jan 24, 2013 at 6:29 PM, Jesús Gabriel y Galán wrote: > On Thu, Jan 24, 2013 at 6:18 PM, tamouse mailing lists > wrote: >> I have some API calls I'm making, all with the following sort of >> begin-rescue-end wrapper: >> >> (pseudo-code) >> >> retries = 0 >> begin >> response = SomeAPI.api_method1(:request => { 'ThisId' => this_id }) >> rescue API::Exception => e >> retries.succ That #succ won't do anything because the result is not stored. >> sleep( retries * 5 ) >> retry unless retries > 2 You are sleeping too much here because after the last attempt you are sleeping as well. Reason is that the decision to retry is made after sleeping. Grouping that in an if end would be better. >> end >> >> where there are multiple api_methods and request forms. Seems like I >> should be able to DRY this instead of doing this everywhere I have to >> make this sort of API call. > > You could create a method for it (untested): > > def call_with_retries obj, method, *args, retries=2 > begin > response = obj.send(method, *args) > rescue API::Exception => e > retries -= 1 > sleep( retries * 5 ) > retry unless retries < 0 > end > end > > and call it like > > call_with_retries SomeApi, :api_method1, :request => { 'ThisId' => this_id } > > You could also pass the exception to rescue, or just rescue > StandardError, and also pass the time to sleep. > Hope this gives you some ideas. I'd rather put the code to invoke into a block because it gives much more flexibility and separates concerns: def retry_code(retries = 2) count ||= 0 yield rescue API::Exception => e count += 1 if count <= retries sleep count * 5 retry end end response = retry_code { SomeAPI.api_method1(:request => { 'ThisId' => this_id }) } Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/