Home » Php » php – Retry a try/catch when it fails

php – Retry a try/catch when it fails

Posted by: admin July 12, 2020 Leave a comment

Questions:

I’ve tried a few different try/catch loops to try and solve problems automatically but they always seem to cause the software to die.

$doLoop = true;

while ($doLoop) {

    try {
        //do a thing
        insertIntoDb($data);
    } catch (Exception $e) {
        //try again
        insertIntoDb($data);
        //write error to file
        writeError($e);
    }
}

Here’s my original try/catch.

The issue is sometimes the MySQL server ‘goes away’ and I need to catch that exception and keep retrying until it comes back.

What can I change here to get this to keep retrying until successful?

How to&Answers:

use a break as last statement in your try block to leave the loop only on success:

while (true) {
    try {
        // do something
        insertIntoDb($data);
        break;
    } 
    catch (Exception $e) {
        writeError($e);
    }
    // sleep 200ms to give the MySQL server time to come back up
    usleep(200000);
}

But you should also limit the number of retries by using a for loop instead.
Otherwise, your code might run in an infinite loop:

// limit the number of retries
for ($i=1; $i <= 3; $i++) {
    try {
        // do something
        insertIntoDb($data);
        break;
    } 
    catch (Exception $e) {
        writeError($e);
    }
    // sleep 200ms to give the MySQL server time to come back up
    usleep(200000);
}

Also note the usleep() call:

This is important because otherwise the PHP process would take all resources (100% CPU) while retrying as fast as possible. You can adjust the value to fit your needs. (maybe 200ms is too long or too short in your case)

Also note that you may need to reconnect to the MySQL DB on failure! I did not include code for that case in my example.

Answer:

This will only work, if your function insertIntoDb will throw an Exception. If you use mysql* functions, then it won’t work.

After insertIntoDb($data); you should set $doLoop = false