После выката на рабочем сайте прогрева не было вообще. В очереди — 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 секунд очередь была пуста: сторож поставил событие сам, воркер отработал.

Не путайте со штатным состоянием. Во время прогона замок стоит, а следующего события ещё нет — он поставит его в конце. «Замок есть, события нет» в моменте — норма; перепроверьте через минуту.

Прогрев иногда просто перестаёт работать?

Пришлите адрес — проверю, может ли у вас оборваться цепочка крона.

· полезно?
АЧ
Алексей Чикун веб-разработчик, команда TRIOHEAD

Делаю сайты и сервисы целиком: от вёрстки до сервера. Пишу о том, что проверил на своих проектах.

Комментарии

// загружаю комментарии…

Комментарии публикуются после проверки. Ссылки и HTML не принимаются.