Seal live dashboard event gaps
This commit is contained in:
@@ -69,17 +69,43 @@ function db_check($sth, &$answer, $options = []) {
|
||||
|
||||
|
||||
|
||||
// Run a callback after the surrounding dbTransaction() commits. If no managed
|
||||
// transaction is active, run immediately. Used for non-authoritative side effects
|
||||
// such as live dashboard notifications.
|
||||
function db_after_commit(callable $callback): void {
|
||||
if (!isset($GLOBALS['_db_after_commit_stack']) || empty($GLOBALS['_db_after_commit_stack'])) {
|
||||
$callback();
|
||||
return;
|
||||
}
|
||||
|
||||
$idx = count($GLOBALS['_db_after_commit_stack']) - 1;
|
||||
$GLOBALS['_db_after_commit_stack'][$idx][] = $callback;
|
||||
}
|
||||
|
||||
// transaction wrapper with retry logic for deadlocks
|
||||
function dbTransaction($pdo, $callback, $maxRetries = 3) {
|
||||
for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
|
||||
$GLOBALS['_db_after_commit_stack'][] = [];
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
$result = $callback($pdo);
|
||||
$pdo->commit();
|
||||
|
||||
$callbacks = array_pop($GLOBALS['_db_after_commit_stack']);
|
||||
foreach ($callbacks as $after_commit) {
|
||||
try {
|
||||
$after_commit();
|
||||
} catch (Throwable $e) {
|
||||
error_log("[AFTER COMMIT ERROR] " . $e->getMessage() . " | " . $e->getFile() . ":" . $e->getLine());
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (PDOException $e) {
|
||||
$pdo->rollBack();
|
||||
if ($pdo->inTransaction()) $pdo->rollBack();
|
||||
array_pop($GLOBALS['_db_after_commit_stack']);
|
||||
|
||||
if ($e->getCode() == '40001' && $attempt < $maxRetries - 1) {
|
||||
usleep(600000 * ($attempt + 1));
|
||||
@@ -90,7 +116,8 @@ function dbTransaction($pdo, $callback, $maxRetries = 3) {
|
||||
throw $e;
|
||||
|
||||
} catch (Exception $e) {
|
||||
$pdo->rollBack();
|
||||
if ($pdo->inTransaction()) $pdo->rollBack();
|
||||
array_pop($GLOBALS['_db_after_commit_stack']);
|
||||
error_log("[ERROR] " . $e->getMessage() . " | " . $e->getFile() . ":" . $e->getLine());
|
||||
throw $e;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user