75 lines
2.8 KiB
PHP
75 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace MonetaPhpShop\host;
|
|
|
|
use MonetaPhpShop\callback\LogThrottle;
|
|
use MonetaPhpShop\ModuleInfo;
|
|
use RuntimeException;
|
|
|
|
/**
|
|
* {@see LogThrottle} â îòäåëüíîé òàáëèöå `[base] moneta_log_throttle` (îäíà ñòðîêà): `logged_at` —
|
|
* âðåìÿ ïîñëåäíåé çàïèñàííîé ñòðîêè, `skipped` — ñêîëüêî ïðîïóùåíî ïîñëå íå¸. Íå â òàáëèöå
|
|
* íàñòðîåê: çàïèñü â MyISAM áëîêèðóåò òàáëèöó öåëèêîì, à íàñòðîéêè ÷èòàåò êàæäûé êîëáýê è êàæäàÿ
|
|
* ñòðàíèöà ñ ôîðìîé îïëàòû — ïîòîê ìóñîðíûõ çàïðîñîâ çàäåðæèâàë áû íàñòîÿùèå óâåäîìëåíèÿ.
|
|
*
|
|
* Çàõâàò ìåòêè — îäèí àòîìàðíûé çàïðîñ, ïîýòîìó èç îäíîâðåìåííûõ çàïðîñîâ ñòðîêó ïèøåò îäèí;
|
|
* ñ÷¸ò÷èê ïðîïóñêîâ ïðè ãîíêå ìîæåò ñáèòüñÿ íà åäèíèöó. Ñòðîêè íåò
|
|
* (óäàëèëè ðóêàìè, ìèãðàöèÿ íå âñòàâèëà) — òîò æå çàïðîñ å¸ ñîçäà¸ò: èíà÷å îáà UPDATE
|
|
* çàòðàãèâàëè áû 0 ñòðîê è îòêàçû ìîë÷à ïðîïàäàëè áû èç æóðíàëà.
|
|
*/
|
|
final class MysqlLogThrottle implements LogThrottle
|
|
{
|
|
/** Åäèíñòâåííàÿ ñòðîêà ñ÷¸ò÷èêà (`install/module.sql`). */
|
|
private const ROW_ID = 1;
|
|
|
|
/** @var Database */
|
|
private $database;
|
|
|
|
public function __construct(Database $database)
|
|
{
|
|
$this->database = $database;
|
|
}
|
|
|
|
public function pass(int $now, int $interval): ?int
|
|
{
|
|
$table = self::table();
|
|
|
|
// Çàòðîíóòûå ñòðîêè: 1 — ñòðîêè íå áûëî è îíà âñòàâëåíà, 2 — ìåòêà îáíîâëåíà,
|
|
// 0 — îêíî åù¸ îòêðûòî è ñòðîêà íå èçìåíèëàñü. Âðåìÿ â áóäóùåì (÷àñû ñåðâåðà ïåðåâåëè
|
|
// íàçàä) — íå æäàòü, ïîêà äîãîíÿò.
|
|
$claimed = $this->database->execute(
|
|
'INSERT INTO `' . $table . '` (`id`, `logged_at`, `skipped`) VALUES (' . self::ROW_ID . ', ?, 0)'
|
|
. ' ON DUPLICATE KEY UPDATE `logged_at` = IF(`logged_at` <= ? OR `logged_at` > ?, ?, `logged_at`)',
|
|
[$now, $now - $interval, $now, $now],
|
|
);
|
|
if ($claimed === 0) {
|
|
$this->database->execute('UPDATE `' . $table . '` SET `skipped` = `skipped` + 1');
|
|
|
|
return null;
|
|
}
|
|
|
|
$skipped = (int) $this->database->fetchValue('SELECT `skipped` FROM `' . $table . '` LIMIT 1');
|
|
if ($skipped > 0) {
|
|
$this->database->execute(
|
|
'UPDATE `' . $table . '` SET `skipped` = GREATEST(`skipped` - ?, 0)',
|
|
[$skipped],
|
|
);
|
|
}
|
|
|
|
return $skipped;
|
|
}
|
|
|
|
public static function table(): string
|
|
{
|
|
$table = $GLOBALS['SysValue']['base'][ModuleInfo::PATH]['moneta_log_throttle'] ?? null;
|
|
// ßâíûé êëàññ, à íå \w: â cp1251-ëîêàëè PHPShop \w ïðîïóñòèë áû êèðèëëèöó (êàê â OperationRepository).
|
|
if (!is_string($table) || preg_match('/\A[0-9A-Za-z_]+\z/', $table) !== 1) {
|
|
throw new RuntimeException('Íåò òàáëèöû ñ÷¸ò÷èêà æóðíàëà â êîíôèãóðàöèè ìîäóëÿ.');
|
|
}
|
|
|
|
return $table;
|
|
}
|
|
}
|