database.php: add retry_on_deadlock utility function

This commit is contained in:
Zankaria 2024-09-14 17:49:40 +02:00
parent 66cb9728b7
commit 5e97b60ebf

View file

@ -6,6 +6,9 @@
defined('TINYBOARD') or exit;
// https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html
const MYSQL_ER_LOCK_DEADLOCK = 1213;
class PreparedQueryDebug {
protected $query, $explain_query = false;
@ -147,6 +150,32 @@ function query($query) {
return $pdo->query($query);
}
/**
* @param int $max_retries The maximum number of times the callable may be re-executed on deadlock detection.
* @param callable $query_func A callable that executes a query. Must throw a PDOException on deadlocks.
* @return mixed The value returned by $query_func.
* @throws PDOException Throws once the maximum number of retries have been attempted.
*/
function retry_on_deadlock(int $max_retries, callable $query_func) {
// Add the first original attempt to the max count.
$max_retries += 1;
$attempt = 0;
while (true) {
$attempt++;
try {
return $query_func();
} catch (\PDOException $e) {
if ($e->errorInfo === null || $e->errorInfo[1] != MYSQL_ER_LOCK_DEADLOCK || $attempt >= $max_retries) {
throw $e;
}
// Wait for 0.5s before retrying...
usleep(500000);
}
}
}
function db_error($PDOStatement = null) {
global $pdo, $db_error;