Retry After an Exception in a PHP Try/Catch Block

I originally posted this on Twitter and made a Gist, but thought I’d write a bit more about the subject of retrying after an exception is thrown in a PHP try/catch block. Since we’re all Laravel developers now and the world is run on APIs, we should recognize our apps are going to call the outside world. Minimally, you’ll be doing this for third-party email service providers, but there are a host of other endpoints your app may need to access. Most of the time, these calls go well. When they don’t, pain ensues.

No matter how reliable the called endpoint may be, there will always be some amount of errors returned. In my experience, many of these can be chalked up to transient network issues or configuration changes that have unintended consequences. When you try to call a service and the SDK or endpoint returns an exception, you’ll generally want to retry the call.

In Laravel, you can take all the pain away from this problem by using queues with retries. Job fails? Toss it back on the queue a few times and retry. However, sometimes you can’t use a queue or don’t want to go to the bother. That’s where looping over the try/catch comes in handy:

/**
 * Basic structure for retrying when an exception is thrown in a try/catch block.
 * This example fails through three retries simply to illustrate the behavior.
 */
$retries = 3;
for ($try = 0; $try < $retries; $try++) {
    try {
        throw new \Exception('bad mojo');
    } catch (\Exception $e) {
        var_dump('failed ' . $try);
        sleep(1);
        continue;
    }
    break;
}

In the above example, we’re throwing a generic exception in the try block just to trigger the behavior in the catch block such that we fail through all our retries.

Pay attention to where you place the break–especially if you have some branching in the try. You might want to move it up. Also, use a reasonable amount of sleep() or usleep(). In the example, we’re only sleeping a second because it’s an example. In the real world, you might want to sleep a little longer before retrying. You also may want to do some logging of the exception. If you don’t log it, it didn’t happen. Have any other ideas/advice? Leave it in the comments!

Leave a Comment

Your email address will not be published. Required fields are marked *