anti-bot.php: use transactions

This commit is contained in:
Zankaria 2024-11-28 16:01:24 +01:00
parent 73bc23a4c7
commit b459551ccb

View file

@ -190,55 +190,63 @@ class AntiBot {
}
}
function _create_antibot($board, $thread) {
function _create_antibot($pdo, $board, $thread) {
global $config, $purged_old_antispam;
$antibot = new AntiBot(array($board, $thread));
// Delete old expired antispam, skipping those with NULL expiration timestamps (infinite lifetime).
if (!isset($purged_old_antispam) && $config['auto_maintenance']) {
$purged_old_antispam = true;
purge_old_antispam();
}
retry_on_deadlock(4, function() use($thread, $board, $config) {
// Keep the now invalid timestamps around for a bit to enable users to post if they're still on an old version of
// the HTML page.
// By virtue of existing, we know that we're making a new version of the page, and the user from now on may just reload.
if ($thread) {
$query = prepare('UPDATE ``antispam`` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE `board` = :board AND `thread` = :thread AND `expires` IS NULL');
} else {
$query = prepare('UPDATE ``antispam`` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE `board` = :board AND `thread` IS NULL AND `expires` IS NULL');
}
$query->bindValue(':board', $board);
if ($thread) {
$query->bindValue(':thread', $thread);
}
$query->bindValue(':expires', $config['spam']['hidden_inputs_expire']);
// Throws on error.
$query->execute();
});
try {
$hash = $antibot->hash();
$pdo->beginTransaction();
// Delete old expired antispam, skipping those with NULL expiration timestamps (infinite lifetime).
if (!isset($purged_old_antispam) && $config['auto_maintenance']) {
$purged_old_antispam = true;
purge_old_antispam();
}
retry_on_deadlock(4, function() use($config, $board, $thread) {
// Keep the now invalid timestamps around for a bit to enable users to post if they're still on an old version of
// the HTML page.
// By virtue of existing, we know that we're making a new version of the page, and the user from now on may just reload.
if ($thread) {
$query = prepare('UPDATE ``antispam`` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE `board` = :board AND `thread` = :thread AND `expires` IS NULL');
} else {
$query = prepare('UPDATE ``antispam`` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE `board` = :board AND `thread` IS NULL AND `expires` IS NULL');
}
retry_on_deadlock(2, function() use($board, $thread, $hash) {
// Insert an antispam with infinite life as the HTML page of a thread might last well beyond the expiry date.
$query = prepare('INSERT INTO ``antispam`` VALUES (:board, :thread, :hash, UNIX_TIMESTAMP(), NULL, 0)');
$query->bindValue(':board', $board);
$query->bindValue(':thread', $thread);
$query->bindValue(':hash', $hash);
if ($thread) {
$query->bindValue(':thread', $thread);
}
$query->bindValue(':expires', $config['spam']['hidden_inputs_expire']);
// Throws on error.
$query->execute();
});
} catch(\PDOException $e) {
if ($e->errorInfo === null || $e->errorInfo[1] != MYSQL_ER_LOCK_DEADLOCK) {
throw $e;
} else {
error_log('Multiple deadlocks on _create_antibot while inserting, skipping');
try {
$hash = $antibot->hash();
retry_on_deadlock(2, function() use($board, $thread, $hash) {
// Insert an antispam with infinite life as the HTML page of a thread might last well beyond the expiry date.
$query = prepare('INSERT INTO ``antispam`` VALUES (:board, :thread, :hash, UNIX_TIMESTAMP(), NULL, 0)');
$query->bindValue(':board', $board);
$query->bindValue(':thread', $thread);
$query->bindValue(':hash', $hash);
// Throws on error.
$query->execute();
});
} catch(\PDOException $e) {
if ($e->errorInfo === null || $e->errorInfo[1] != MYSQL_ER_LOCK_DEADLOCK) {
throw $e;
} else {
error_log('Multiple deadlocks on _create_antibot while inserting, skipping');
}
}
} catch (\PDOException $e) {
$pdo->rollBack();
throw $e;
}
$pdo->commit();
return $antibot;
}