Effective Ruby: 48 Specific Ways to Write Better Ruby by Peter J. Jones

Effective Ruby: 48 Specific Ways to Write Better Ruby by Peter J. Jones

Author:Peter J. Jones [Jones, Peter J.]
Language: eng
Format: epub
Tags: Programming Languages, Computers, Ruby, General
ISBN: 9780133846973
Google: pzd_BAAAQBAJ
Publisher: Pearson Education
Published: 2014-09-01T21:14:37+00:00


Item 26: Bound retry Attempts, Vary Their Frequency, and Keep an Audit Trail

Item 23 explains why it’s important to rescue only those specific exceptions which you know how to handle and how things can go wrong when using rescue. I recommend you familiarize yourself with the ramifications involved when using rescue because this item expands on that idea by demonstrating how to resolve an error condition by rerunning the code which caused it.

Although not very common, certain errors can be safely handled by rescuing the resulting exception and restarting the enclosing scope with the retry keyword. Suppose you’ve written a program which communicates with a third party vendor using a fancy web API. When specific records in your database change your code kicks off and attempts to transmit the changes to the vendor. The only problem is, the vendor is running some very buggy software. 1 out of every 30 requests you make result in a response informing you that your data transfer failed due to a database deadlock error. Good news though, the vendor is aware of the problem and should have it fixed in the next three months.

After some experimenting you discover a simple workaround, retrying the request after a short delay results in a successful transaction. With hundreds of these failures an hour, this task clearly needs to be automated. A natural first attempt might look something like this:

begin

service.update(record)

rescue VendorDeadlockError

sleep(15)

retry

end

There’s a major problem with this code that isn’t immediately obvious. Testing this code—even putting it into production—might work for a bit of time until an unexpected edge case is encountered. The problem lies with how we’re using retry and the fact that it creates a hidden loop in the code. As long as the update method continues to raise a VendorDeadlockError the block will continue to get restarted. Writing an unconditional retry is akin to writing an infinite loop. To make this clearer consider this use of while which emulates our first attempt at using retry:

while true

begin

service.update(record)

rescue VendorDeadlockError

sleep(15)

# Drop exception

else

break # Success, exit loop.

end

end

This is quite a bit uglier but it does make the loop explicit. If we’re going to use retry then we need to take this implicit loop into consideration. One correct solution is to place an upper bound on the number of retry attempts. This is often done with a bounding variable. The tricky part is ensuring that this variable is correctly scoped:

retries = 0



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.