Детектор выката (двадцатая часть) проверяется на каждом запросе к PHP. После выката первым его может заметить живой посетитель, а может — системный крон. Иногда оба в одну и ту же секунду. Тогда два полных сброса идут одновременно и рвут каталог кэша друг у друга (двадцать вторая часть) — а прогрев встаёт дважды.
Это двадцать третья часть цикла «Кэш страниц без MISS».
Почему не помогает add_option
Обычная идея — «замок» опцией: кто первым создал опцию, тот и сбрасывает. Но add_option сначала проверяет, есть ли опция, а потом пишет. Между этими шагами второй процесс успевает сделать ту же проверку. Оба видят «опции нет», оба создают, оба сбрасывают.
Атомарный замок
База данных умеет делать проверку и запись одной операцией: вставка с IGNORE по уникальному ключу. Вставил тот, у кого вернулась одна затронутая строка.
function cache_purge_lock(): bool {
global $wpdb;
$name = 'cache_purge_lock';
// протухший замок (процесс упал) — убрать
$wpdb->query($wpdb->prepare(
"DELETE FROM {$wpdb->options} WHERE option_name = %s AND option_value < %d",
$name, time() - 300
));
$ok = $wpdb->query($wpdb->prepare(
"INSERT IGNORE INTO {$wpdb->options} (option_name, option_value, autoload)
VALUES (%s, %s, 'no')",
$name, (string) time()
));
return $ok === 1;
}
if (cache_purge_lock()) {
try {
cache_purge_all();
do_action('cache_purged'); // сигнал шлёт только владелец замка
} finally {
delete_option('cache_purge_lock');
}
}
- протухание через 5 минут — если процесс упал, не сняв замок, следующий выкат не застрянет навсегда;
- try/finally — замок снимается даже при ошибке внутри сброса;
- сигнал шлёт только владелец — круг прогрева встаёт один раз.
Таблица опций уже имеет уникальный ключ по имени опции — отдельную таблицу для замка заводить не нужно.
Странности с кэшем сразу после выката?
Пришлите адрес — проверю, не сталкиваются ли у вас два сброса.
// загружаю комментарии…