Посетитель рендерит один блок за запрос — и процесс 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/
Диагностика вручную. Если запустить воркер вручную, пока его же запустил крон, ручной запуск молча выйдет по замку — и покажется, что «всё работает, ошибок нет». Сначала снимите замок.
В кэше лежат блоки, которые выглядят не так?
Пришлите адрес — проверю, не делят ли рендеры глобальное состояние.
// загружаю комментарии…