Полный сброс кэша — это обход каталога кэша с удалением файлов. Простая задача, пока по тому же каталогу не ходит кто-то ещё. А ходит всегда: nginx сам удаляет и создаёт файлы, его менеджер кэша чистит устаревшее.
Это двадцать вторая часть цикла «Кэш страниц без MISS».
Что увидели
Через 6 минут после выката — 634 из 640 страниц MISS, очередь обходчика пуста. Сброс в журнале есть, круга прогрева нет.
Почему
Итератор по каталогу открывает подкаталог в момент, когда до него доходит. Если подкаталог исчез между чтением родителя и открытием — исключение. Обработчик ловил его и делал return. А сигнал «сброс выполнен», на который подписан прогрев, стоял после цикла. До него дело не доходило.
try {
foreach ($it as $file) { @unlink($file->getPathname()); }
} catch (UnexpectedValueException $e) {
error_log('purge: ' . $e->getMessage());
return; // ← прогрев не встанет
}
do_action('cache_purged');
Лечение
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(CACHE_DIR, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD // пропускать исчезнувшие подкаталоги
);
try {
foreach ($it as $file) {
$p = $file->getPathname();
$file->isDir() ? @rmdir($p) : @unlink($p); // «уже удалено» — не ошибка
}
} catch (UnexpectedValueException $e) {
error_log('purge: ' . $e->getMessage()); // залогировать, но не выходить
}
do_action('cache_purged'); // сигнал — всегда
CATCH_GET_CHILD— итератор пропускает подкаталог, который не смог открыть, вместо исключения;- отсутствующий файл при удалении — не ошибка, его уже удалили за нас;
- catch без return: сигнал прогрева отправляется в любом случае.
Как воспроизвести
Важно удалять подкаталоги уже прочитанного родителя, которые итератор ещё не открыл. Удаление ещё не открытого родителя ошибку не воспроизводит. С таким воспроизведением старый цикл оставлял 568 записей, новый — 0.
После выката весь сайт холодный?
Пришлите адрес — проверю, доходит ли у вас сброс до прогрева.
// загружаю комментарии…