cacheRegenerator. Авторегенерация кеша страниц
Сегодня публикую маленький, но очень полезный компонент (надеюсь в течение дня будет одобрен в modstore.pro). Сейчас это всего один плагин. Задача его состоит в том, чтобы сразу после сохранения документа выполнять регенерацию этой страницы, чтобы даже при первом заходе посетителя, документ уже был в кеше и отдавался быстрее.
Зачем это нужно? Покажу наглядно.
Вот у нас сайт некоторое время поработал и большинство страниц идет из кеша.

Но тут мы отредактировали и сохранили один документ. Что произошло? Сбросился кеш для всех страниц вообще, и теперь при первом заходе на каждую страницу выполняется много лишних действий (первичная выборка данных документа, сниппетов, чанков и прочего из БД, проверка прав и т.п.). Из-за этого скорость генерации страниц сильно падает.

И здесь, казалось бы, возникает простой понятный сценарий: сбрасывать кеш только той страницы, которая редактируется. Но не все так просто… Проблема в том, что эта страница может участвовать в различных выборках (к примеру, новостная лента), и сбросив кеш только этой страницы, но не спросив кеш других страниц, может возникнуть коллизия: на странице обновленной новости будет один контент, а в новостной выборке другой контент. По этой причине очевидно, что необходим функционал не только регенерации текущей редактируемой страницы, но и регенерация всех страниц при полном сбросе кеша сайта. Собственно, этот функционал так же был реализован в этом компоненте, но по умолчанию отключен в системных настройках, так как если страниц много, то при сохранении документа будет долго выполняться запрос на сохранение, а может и вовсе запрос отваливаться по таймлимиту. Автоматическую регенерацию всех страниц имеет смысл включать только если на сайте всего несколько десятков страниц.
Итак, есть три основных режима:
1. Полный сброс кеша при редактировании страницы и автоматическая регенерация всех страниц.
Для этого должна быть включена системная настройка cacheregenerator.regenerate_docs_on_doc_save
2. Регенерация только текущего редактируемого документа. При этом кеш остальных документов не сбрасывается.
Соответственно настройка cacheregenerator.regenerate_docs_on_doc_save должна быть отключена.
3. Автоматическая регенерация всех страниц при ручном вызове сброса кеша сайта.
Должна быть включена настройка cacheregenerator.regenerate_docs_on_site_refresh
Но наиболее правильная, на мой взгляд конфигурация: отключить системную настройку syncsite_default и все. В этом случае при сохранении документа не будет выполняться сброс кеша всех документов. При сохранении cacheRegenerator будет сбрасывать кеш только текущего документа и заново его регенерировать. Тогда не придется переживать за то, что после каждого сохранения документа сбрасывается полностью кеш. Только надо не забывать сбрасывать кеш вручную, если надо будет, чтобы все зависимые документы тоже обновились. Вот тогда после сохранения документа остальные документы будут по прежнему из кеша отдаваться.

Кстати, с syncsite_default отдельный казус:) Если его отключить, то не только всех документов не скидывается кеш, но и текущего редактируемого. То есть в случае отключения этой настройки, даже для редактируемого документа, чтобы изменения вступили в силу, приходится вручную сбрасывать кеш. Эту проблему пришлось тоже решать.
На самом деле подводных камне здесь оказалось много…
Там и проверка доступа к документу неавторизованных пользователей, и правильное кеширование документов в цикле (надо правильно скидывать временные свойства объекта $modx), и прочие «приятные» мелочи. Без учета их то документы с единым контентом сохранялись, то скрипт отваливался, то еще что).
Отдельная песня — перехват заголовков. Ведь при вызове документа может срабатывать какой-нибудь сниппет с проверками прав (типа сброс пароля, к примеру), и тот отдает 404 или 401, из-за чего так же скрипт отваливался. Пришлось хак прописать со сбросом буферизации вывода и выводить простой пробел, чтобы заголовки не отправлялись. В общем этот компонент скушал весьма не мало времени. Я искренне надеюсь, что он будет полезен многим.
Еще момент: есть системные настройки cacheregenerator.exclude_doc_templates_id (можно через запятую указать id-шники шаблонов, документы с которыми исключить из регенерации), cacheregenerator.exclude_docs_id (так же список id-шников документов через запятую, которые исключить надо), и cacheregenerator.regenerate_unsearchable_docs (исключить документы, не доступные для поиска (как правило это всякие технические документы)). Это надо, так как не все получается перехватить и сниппеты с вызовом редиректов и т.п. могут обрывать выполнение скрипта. Вот такие документы и надо исключать.
Цена на него относительно не высокая — 990 рублей, и будет долго такой оставаться (расчет на массовость). Если интерес будет, добавим механизм консольной перегенерации документов. Сейчас такое у нас реализовано на отдельном проекте базе modImporter.

P.S. Компонент опубликован в modstore.pro
UPD Уточнение: на скриншотах не cacheRegenerator, а modMonitor. С помощью монитора я показываю результат работы компонента, но сам cacheRegenerator не имеет интерфейсов.
Зачем это нужно? Покажу наглядно.
Вот у нас сайт некоторое время поработал и большинство страниц идет из кеша.

Но тут мы отредактировали и сохранили один документ. Что произошло? Сбросился кеш для всех страниц вообще, и теперь при первом заходе на каждую страницу выполняется много лишних действий (первичная выборка данных документа, сниппетов, чанков и прочего из БД, проверка прав и т.п.). Из-за этого скорость генерации страниц сильно падает.

И здесь, казалось бы, возникает простой понятный сценарий: сбрасывать кеш только той страницы, которая редактируется. Но не все так просто… Проблема в том, что эта страница может участвовать в различных выборках (к примеру, новостная лента), и сбросив кеш только этой страницы, но не спросив кеш других страниц, может возникнуть коллизия: на странице обновленной новости будет один контент, а в новостной выборке другой контент. По этой причине очевидно, что необходим функционал не только регенерации текущей редактируемой страницы, но и регенерация всех страниц при полном сбросе кеша сайта. Собственно, этот функционал так же был реализован в этом компоненте, но по умолчанию отключен в системных настройках, так как если страниц много, то при сохранении документа будет долго выполняться запрос на сохранение, а может и вовсе запрос отваливаться по таймлимиту. Автоматическую регенерацию всех страниц имеет смысл включать только если на сайте всего несколько десятков страниц.
Итак, есть три основных режима:
1. Полный сброс кеша при редактировании страницы и автоматическая регенерация всех страниц.
Для этого должна быть включена системная настройка cacheregenerator.regenerate_docs_on_doc_save
2. Регенерация только текущего редактируемого документа. При этом кеш остальных документов не сбрасывается.
Соответственно настройка cacheregenerator.regenerate_docs_on_doc_save должна быть отключена.
3. Автоматическая регенерация всех страниц при ручном вызове сброса кеша сайта.
Должна быть включена настройка cacheregenerator.regenerate_docs_on_site_refresh
Но наиболее правильная, на мой взгляд конфигурация: отключить системную настройку syncsite_default и все. В этом случае при сохранении документа не будет выполняться сброс кеша всех документов. При сохранении cacheRegenerator будет сбрасывать кеш только текущего документа и заново его регенерировать. Тогда не придется переживать за то, что после каждого сохранения документа сбрасывается полностью кеш. Только надо не забывать сбрасывать кеш вручную, если надо будет, чтобы все зависимые документы тоже обновились. Вот тогда после сохранения документа остальные документы будут по прежнему из кеша отдаваться.

Кстати, с syncsite_default отдельный казус:) Если его отключить, то не только всех документов не скидывается кеш, но и текущего редактируемого. То есть в случае отключения этой настройки, даже для редактируемого документа, чтобы изменения вступили в силу, приходится вручную сбрасывать кеш. Эту проблему пришлось тоже решать.
На самом деле подводных камне здесь оказалось много…
Там и проверка доступа к документу неавторизованных пользователей, и правильное кеширование документов в цикле (надо правильно скидывать временные свойства объекта $modx), и прочие «приятные» мелочи. Без учета их то документы с единым контентом сохранялись, то скрипт отваливался, то еще что).
Отдельная песня — перехват заголовков. Ведь при вызове документа может срабатывать какой-нибудь сниппет с проверками прав (типа сброс пароля, к примеру), и тот отдает 404 или 401, из-за чего так же скрипт отваливался. Пришлось хак прописать со сбросом буферизации вывода и выводить простой пробел, чтобы заголовки не отправлялись. В общем этот компонент скушал весьма не мало времени. Я искренне надеюсь, что он будет полезен многим.
Еще момент: есть системные настройки cacheregenerator.exclude_doc_templates_id (можно через запятую указать id-шники шаблонов, документы с которыми исключить из регенерации), cacheregenerator.exclude_docs_id (так же список id-шников документов через запятую, которые исключить надо), и cacheregenerator.regenerate_unsearchable_docs (исключить документы, не доступные для поиска (как правило это всякие технические документы)). Это надо, так как не все получается перехватить и сниппеты с вызовом редиректов и т.п. могут обрывать выполнение скрипта. Вот такие документы и надо исключать.
Цена на него относительно не высокая — 990 рублей, и будет долго такой оставаться (расчет на массовость). Если интерес будет, добавим механизм консольной перегенерации документов. Сейчас такое у нас реализовано на отдельном проекте базе modImporter.

P.S. Компонент опубликован в modstore.pro
UPD Уточнение: на скриншотах не cacheRegenerator, а modMonitor. С помощью монитора я показываю результат работы компонента, но сам cacheRegenerator не имеет интерфейсов.
Комментарии: 28
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
P.S. Глупый вопрос наверное, но со страницами от miniShop'а и подобным им конфликтов не будет?
Fi1osofFi1osofДавай по порядку.
Во-первых, у тебя там всего три строчки на «создание кеша».
То есть простой запрос на УРЛ документа (кстати, об этом еще чуть ниже будет сказано).
У меня же плагин 200+ строк кода. Для того, чтобы сгенерировать кеш документа, я не шлю какие-то GET-запросы на внешние ресурсы, а именно гененерирую кеш на уровне выполнения самого скрипта. И там поверь, очень много тонкостей.
У тебя возникает вопрос нафига вообще так все усложнять? Почему не слать простой запрос? Я отвечу. Во-первых, задача ставилась не только генерировать кеш текущего редактируемого документа, но и кеш остальных документов тоже. Но ты, видимо, этого в статье не увидел, «дежавю» ослепило тебя. Вот смотри, что происходит при сохранении документа после полного сброса кена при включенной настройке генерации кеша всех документов (или настройке регенерации при полном сбросе кеша):
После чего даже все другие документы доступны сразу из кеша:
Ткни пальцем, где твой компонент умеет генерировать кеш остальных документов?
Кстати, тебе на заметку: при вызове обновления документов через процессоры напрямую, твой плагин не генерит кеш документа, потому что ты проверяешь глобальную $_POST['createCache'], а не $resource->get('createCache'). Не знал, что обновляемым объектам все передаваемые в процессор параметры присваиваются? Просто в БД не пишется лишнего.
Во-вторых, слышал про мультидоменность и мультиконтекстность? Давай посмотрим, что происходит при сохранении документов с твоим великим плагином?
Ой, 404-ая. А при заходе на документ по реальной ссылке во фронте, получаем его не из кеша.
А с моим плагином как? А с моим все хорошо. Он корректно определил контекст и сформировал корректный запрос.
Так что конечно можешь продолжать бесплатно свое раздавать. Оно же работает кое-как. Это нормально. А когда сделаешь, чтобы работало как у меня, тогда посмотрим насколько оно у тебя будет бесплатное, и не похожее на то, как у меня сделано.
И еще: если вдруг ты доработаешь свое «творение», и оно будет «генерировать» кеш всех документов, как именно ты это будешь делать? Так же слать GET-запросы? То есть на сайте 100 документов, 10 раз отредактировал страницу, ушло 10 раз по 100 запросов на сайт? Мало того, что это 1000 инициализаций MODX-а, так это еще и 1000 записей сессий в БД. А будет 10 человек работать, по 100 сохранений в день? 10*100*100 = 100 000 записей в БД за день? Ну-ну…
P.S. И не думай, что я «идею» подсмотрел у тебя. Поверь на слово, это не так. Я далеко не все твои топики читаю.
И мысли такой не было. Да и Боб Рей со своим refreshCache вряд ли так думает.
Да и без разницы мне чего ты и за сколько делаешь. У меня нет ни желания ни права указывать. Мой комментарий выше не для тебя был (ты вроде обещал их игнорировать). Мы все делаем компоненты для пользователей. Им и выбирать. Смысла в перепалке не вижу.
Fi1osofТы приходишь в мой топик и своим комментарием говоришь «Ха, это все фигня, у меня такое же есть, за что тут вообще денег брать?».
Это не тот случай, когда я могу не обращать внимания на комментарии.
Fi1osofП.С. Что же за жизнь у тебя такая, если ты вместо слов человеческих гавкаешь как собака на всех.
Fi1osofОК, забираю свои слова обратно. Я тоже этого не придерживаюсь.
joxi.ru/1A5be4ahnKDRDr
Просто странно стало, что пока тебя не было, не было и минусов, а потом вдруг раз, и сразу куча упала. Видимо кто-то тут шайками промышляет. Ну да фиг с ним.
давно заметил, что есть тут такая тенденция ставить минусы за то что услугу\продукт продают, ну вот просто за факт продажи — минус, а так как Сергей ссылался на свой бесплатный компонент, то тут и началось, что де кто-то продает, а оно вон есть даром))
К огромному сожалению, эмоции и какие то непонятные ожидания халявы и чудес властвуют над умами))
Всем добра и плюсы. Спасибо за полезные разработки.
Fi1osofPS нужен искусственный интеллект для вычисления веса плюса и минуса)))
Fi1osofЕсть пример сайта, на котором установлен этот модуль, для проверки его скорости загрузки.
Fi1osofЭто вопрос или утверждение? Если вопрос, то здесь скриншотов довольно много. Уточню, что этот компонент не добавит вам скорости там, где ее нет. Он просто позволяет не терять ее там, где обычно теряется. Поэтому, если у вас сайт медленно отдает страницы даже из кеша, он не прибавит им скорости.
Подскажите, пожалуйста, как будет работать cacheRegenerator на сайте с количеством ресурсов 2.2к?
Fi1osofКак я и говорил, на таком количестве не стоит включать настройки cacheregenerator.regenerate_docs_on_site_refresh и cacheregenerator.regenerate_docs_on_doc_save, иначе на сохранение документа и на сброс кеша сайта у вас будет запускаться механизм регенерации страниц, который в среднем занимает 1 сек на страницу (в зависимости от скорости работы сайта). Таким образом полчаса ждать после сохранения документа — вообще не вариант.
Вариант только такой: отключаете системную настройку syncsite_default и при сохранении редактируемого документа не будет сбрасываться кеш остальных документов, а только текущего, при чем у текущего документа кеш сразу будете перегенерирован. Таким образом вы получаете измененное содержимое страницы сразу в кеше.
Fi1osofВ общем, я тут думал как вам помочь, и вспомнил, что давным-давно Илья Уткин дописывал функционал циклического выполнения кода в консоль (За что Илье отдельное спасибо). ilyaut.ru/cheats/step-by-step-the-script-in-console/
В итоге я написал вот такой скрипт: gist.github.com/Fi1osof/398e64212f1c527958adce83734ddf4b
Его можно использовать для ручной перегенерации кеша всех страниц. Если его запустить, он получит ID-шники всех целевых страниц и перегенерирует их кеш. Выглядит процесс довольно симпатично.
Вот можете воспользоваться этим скриптом. Сохраните его в консоли (функционал такой добавил Сергей Шлоков) и выполняйте когда вам надо.
Повторю логику: для того, чтобы не сбрасывался кеш на каждый чих, сделайте как я написал выше. А если вам надо вдруг сбросить кеш всего сайта вручную, то можете запустить потом этот скрипт. Если вам не хочется ждать по полчаса каждый раз, вы можете добавить в условие выборки только самые нагруженные ресурсы (к примеру, по определенным шаблонам).
Кстати, здесь сразу идея возникает связки этого скрипта с modMonitor. Монитор собирает статистику какие страницы не из кеша отдаются долго, и потом при запуске этого скрипта перегенерируются только те страницы, время генерации которых превышает заданный парог. Получится интеллектуально.
Важно: Для работы требуется минимум console-2.2.1
Ее я отправил на modx.com, но пока еще не опубликовали. Можно вручную подправить в консоли вот этот код.
Fi1osofFi1osofДобавил уточнение в топик.
Fi1osof