После выката на рабочем сайте прогрева не было вообще. В очереди — 42 задачи. Следующего запуска воркера — нет. Последний запуск — за 20 минут до выката. Очередь стояла и ждала, пока кто-нибудь положит в неё новую задачу: только это снова ставило событие крона.
Это тридцать пятая часть цикла «Кэш страниц без MISS».
Как устроен воркер на wp-cron
Фоновый воркер в WordPress обычно работает так: разовое событие крона запускает прогон, прогон в конце ставит следующее событие. Цепочка держится на том, что каждый прогон ставит следующий.
add_action('warm_worker', function () {
if (get_transient('warm_lock')) {
return; // ← событие израсходовано, нового нет
}
set_transient('warm_lock', 1, 5 * MINUTE_IN_SECONDS);
// ... прогон ...
delete_transient('warm_lock');
wp_schedule_single_event(time() + 60, 'warm_worker');
});
Если прогон вышел раньше — по замку, по ошибке, по нагрузке, — следующее событие не ставится. Цепочка обрывается. Очередь непуста, а запускать её некому.
Улика: очередь непуста, wp_next_scheduled('warm_worker') === false, время последнего прогона старше выката.
Лечение
- одна функция планирования — все ветки (замок, ошибка, нагрузка, успех) зовут её, никто не ставит событие сам;
- сторож на тике крона — на каждом запуске крона проверяет «очередь непуста, а события нет» и ставит его;
- замок 3 минуты с временем старта вместо 5 — короче простоя, если процесс упал;
- ошибки не гасят весь прогон: «три ошибки подряд — стоп» не должно останавливать цепочку.
function warm_schedule_next(int $delay = 5): void {
if (!wp_next_scheduled('warm_worker')) {
wp_schedule_single_event(time() + $delay, 'warm_worker');
}
}
// сторож: на каждом тике крона
add_action('wp_loaded', function () {
if (wp_doing_cron() && warm_queue_size() > 0) {
warm_schedule_next();
}
});
Как доказали, что фикс работает
Не ждали следующей аварии — сломали руками. На рабочем сайте при 4 задачах в очереди удалили событие крона. Через 130 секунд очередь была пуста: сторож поставил событие сам, воркер отработал.
Не путайте со штатным состоянием. Во время прогона замок стоит, а следующего события ещё нет — он поставит его в конце. «Замок есть, события нет» в моменте — норма; перепроверьте через минуту.
Прогрев иногда просто перестаёт работать?
Пришлите адрес — проверю, может ли у вас оборваться цепочка крона.
// загружаю комментарии…