Посетитель рендерит один блок за запрос — и процесс PHP умирает. Воркер рендерит десятки блоков подряд в одном процессе. Всё, что один рендер оставил после себя в глобальном состоянии, видит следующий. И самое неприятное: сторож полноты этого не замечает, потому что испорченная ячейка есть и лежит как HIT.

Это пятая часть цикла «Кэш фрагментов и Redis».

Блоки без вкладок

Шаблон товара ставил переменную запроса «показать один вариант». У посетителя она умирала вместе с процессом. В воркере она доживала до конца прогона — и все следующие блоки рендерились так, будто их попросили показать один вариант.

Итог: 134 из 139 ячеек блока с вариантами товара лежали без вкладок. Все — HIT. Сторож полноты видел: ячейки есть, версия правильная, всё хорошо.

Лечение: снимок и восстановление

function frag_render_isolated(callable $render, array $args): array {
    global $wp_query, $post;
    $saved_vars = $wp_query->query_vars;
    $saved_post = $post;
    try {
        // параметры выставлять всегда — в том числе пустые,
        // чтобы не унаследовать значение от прошлого рендера
        set_query_var('show_one', $args['show_one'] ?? '');
        return $render($args);
    } finally {
        $wp_query->query_vars = $saved_vars;
        $post = $saved_post;
        wp_reset_postdata();
    }
}

Как это найти

  • маркер в разметке — проверить ячейки на признак, который обязан быть у их группы (у блока вариантов — вкладки). Важно сверять по группам: 342 «без вкладок» на другом блоке оказались законными — у тех товаров один вариант;
  • воспроизведение в одном процессе — отрендерить подряд два разных блока в одном скрипте и сравнить с отдельными рендерами.

Вторая беда того же класса: шаблон объявляет функцию

Шаблон блока объявлял функцию прямо внутри себя. У посетителя шаблон подключается один раз. В воркере — второй рендер того же блока падает с ошибкой «Cannot redeclare». Падает весь прогон, замок держится 3 минуты, затем всё повторяется — по кругу.

После обёртки в function_exists — 18 рендеров за 5,7 секунды.

# найти шаблоны, которые объявляют функции или прерывают выполнение
grep -rn "function [a-zA-Z_]*(" templates/
grep -rnE "\b(die|exit)\b" templates/

Диагностика вручную. Если запустить воркер вручную, пока его же запустил крон, ручной запуск молча выйдет по замку — и покажется, что «всё работает, ошибок нет». Сначала снимите замок.

В кэше лежат блоки, которые выглядят не так?

Пришлите адрес — проверю, не делят ли рендеры глобальное состояние.

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

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

Комментарии

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

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