Кэш и новости, или нагруженные проекты


Хочу немного поделиться о использовании на сайтах кустом кэша. Для начало, поставим себе небольшую задачу.

Небольшой сайт, с лентой новостей и вывода двух или более блоков на любой странице сайта — Последние новости.



Строим структуру новостей. Я советую сразу новости публиковать по папкам, папка — это месяц, так легче наполнять и искать нужную новость.
этап 1
Создаём шаблон для главной странице новостей к примеру contentNewsHome, и для вызова новостей в ресурсе с id-20, будем использовать расширение PageNav.
Код в шаблоне contentNewsHome
[[!PageNav:default=`[[$nocont]]`? &language=`ru`
&elementClass=`modSnippet`
&element=`getResources`
&parents=`[[*id]]`
&depth=`3`
&limit=`9`
&pageLimit=`5`
&sortby=`{"createdon":"DESC"}`
&pageVarKey=`page`
&includeTVs=`1`
&includeContent=`1`
&hideContainers=`1`
&tpl=`NewsPub`
&cache=`true`
]]

соответственно создали сам чанк для вывода новости NewsPub
Как видите, мы параметр cache установили в true, т.е. кэш будет существовать до тех пор, пока мы не произведём ручную очистку сайта от кэша (Сайт -> Обновить сайт). Можно установить параметр cache_expires, задав время хранения в кэше, но это нас не устраивает, так как нам нужно кэш Новостей обновлять, только когда добавили новость, и даже не сами новости (их может быть за 1000, а имено только вывод новостей) По умолчанию, PageNav хранит кэш в отдельной директории от ресурсов —
/core/cache/ pagenav/
, вы можете задать свою директорию, но тогда нужно позаботиться об удалении кэша, для начало — разберёмся с одними новостями.

этап 2
Создаём теперь шаблон, для самой новости, к примеру — News. Допустим у нас новости заполняют менеджеры (можно всех включить ), т.е. переходим к настройкам форм. Безопасность -> Настройка форм. Создаём новый профиль. В профиле, в вкладке Группы пользователей, добавляем наши группы, к которым мы хотим применить наше правило.
Далее — Создать новый набор правила, действие — Update Resource (аналогично и для Create Resource), выбираем наш шаблон — News. Теперь в гриде ищем имя — syncsite, и на против колонки — Значение по умолчанию, ставим 0 (нуль), этим самым мы сняли галочку при создании (Create Resource) или редактировании (Update Resource) ресурса — очищать кэш. Далее уже на своё усмотрения настраиваем поля и убираем в колонке — Видимый, оставляем те поля, которые нам нужно показать.

этап 3
Что мы имеем, При сохранении новости, у нас кэш сайта общего не затрагиваеться, т.е. всё на месте, а как же нам теперь показать добавленную новость в ленте новостей, ведь мы установили параметр cache в true и не указали время… будем писать плагин, который сделает это.
Итак, плагин, к примеру NewsCache
Переходим в вкладку — Системны события, ставим галочку на против параметра OnDocFormSave, и сам код
switch ($modx->event->name) {
	case 'OnDocFormSave':
	$idparent = 20;
	$pids = array();
	$id = $resource->get('id');
	$pids = $modx->getParentIds($id, 4, array('context' => 'web'));
	if (in_array($idparent, $pids)){
		//$modx->log(modX::LOG_LEVEL_INFO,'Clear cache in PagNav');
		$modx->cacheManager->clearCache(array('/pagenav'));
		
		// Path to the resource cache
		$resourcesPath = $modx->getOption('core_path') . 'cache/resource/web/resources/';
		$parents  = array($id);
		// Iterate through parents and remove cache resources
		foreach($parents as $parent) {
			$parentPath = $resourcesPath . $parent . '/';
			if(file_exists($parentPath) && $modx->cacheManager->deleteTree($parentPath, array('deleteTop' => true)))
		unlink($resourcesPath.$parent.'.cache.php');
		}
	}
}

$idparent = 20; — это как раз родитель наших новостей, меняем на свой. Что мы сделали, при сохранении ресурса, проверяем существование этого ресурса в дереве, если да — то убиваем наш кэш в
core/cache/ pagenav/
и убиваем кэш только ресурса который редактирум.

этап 4
Почти конец, но у нас есть ещё блоки — Последние новости. Так как у нас эти блоки одинаковые, не вижу смысла на каждой странице вывода, заносить в отдельный кэш с уникальным ключом.
Вариантом может быть много (можно создать снипет, который будет разрулевать всё, но так как у нас небольшой сайт, то сделаем более просто, расскажу один из них. Делаем копию снипета getResources — к примеру getResourcesNews
и в самом начале снипета getResourcesNews вставляем код
if($modx->getCacheManager()){
  // Creates a key, unique key will be created depending on the parameters passed to the function.
  $keypage = md5('pagenews::left');  
  if ($cachnav = $modx->cacheManager->get($keypage,array(
		xPDO::OPT_CACHE_KEY => 'pagenav'
		))){
	//$modx->setPlaceholder($totalVar,$cachnav['totalVar']);
    return $cachnav['output'];
  }else{
    $inCache = false;
  }
}

и в самом конце снипета getResourcesNews, перед выводом
return $output;
, вставляем код
if ($modx->getCacheManager() && !$inCache ){
  //$cachnav['totalVar'] = $total;
  $cachnav['output'] = $output;
  $modx->cacheManager->set($keypage, $cachnav,0,array(
		xPDO::OPT_CACHE_KEY => 'pagenav'
		));
}

Мы поместили выборку Последние новости в ту же самую директорию кэша, где и сами новости.
Теперь выборку делаем для блока Последние новости через наш снипет getResourcesNews, снипет вызываем не кэшированным. так как мы сами создали управления кэшем.

ФИНАЛ.
Теперь даже при 2000 новостей и 5 тысячах ресурсов, мы при добавлении новости не убиваем весь кэш ресурсов и кэш самих новостей, а только кэш пагинации и самих блоков — Последние новости ( и то, всё в одном кэше)
Для начало думаю достаточно. Вопросы?

Задача
Задача, чтобы понапрягать мозги, к примеру у нас структура новостей более сложная и очень много добавления новостей идёт на сайт. Зачем нам чистить новости из дерева 2011 год (id-30), если новости добовляются только в 2012 год?
ПОДСКАЗКА: Решается она легко, буквально двумя строчками в созданом плагине NewsCache

P.S. это одно из действий, которое можно применить к высоконагруженым проектам. Надеюсь дальше, всё зависит от вашего задания и от вашей фантазии. В Рево нет границ, с ней можно творит чудеса!

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.