Ошибка в моем кеширующем коде

#php

#php

Вопрос:

Вот мой код:

       $cachefile = "cache/ttcache.php";
      if(file_exists($cachefile) amp;amp; ((time() - filemtime($cachefile)) < 900))
      {
            include($cachefile);
      }
      else
      {
            ob_start();

            /*resource-intensive loop that outputs 
            a listing of the top tags used on the website*/

            $fp = fopen($cachefile, 'w');
            fwrite($fp, ob_get_contents());
            fflush($fp);
            fclose($fp);
            ob_end_flush();
      }
  

На первый взгляд казалось, что этот код работает нормально, но я обнаружил ошибку и не могу понять, как ее решить. В принципе, кажется, что после того, как я оставляю страницу в покое на некоторое время, файл кэша очищается (либо это, либо когда я обновляю страницу, он очищает файл кэша, делая его пустым). Затем условие видит теперь пустой файл кэша, определяет его возраст менее 900 секунд и извлекает содержимое пустого файла кэша вместо повторного запуска цикла и повторного заполнения кэша.

Я запустил файл кэша в командной строке и увидел, что он действительно пуст, когда существует эта проблема.

Я попытался установить значение 60 секунд, чтобы чаще повторять эту проблему и, надеюсь, разобраться в ней, но, похоже, она не повторяется, если я ее ищу, только когда я покидаю страницу и возвращаюсь через некоторое время.

Любая помощь?

Комментарии:

1. Вы уверены, что это не фатальная ошибка, которая возникает при повторном рендеринге страницы и скрывается под текущим error_reporting() ?

2. Добавьте фиктивную строку в начало вашего кэша, например '<!--'.time().'-->' , чтобы проверить, что в данный момент сохранено в файле.

3. Привет, очевидно, вы урезали ненужный код (спасибо!), правильный ли порядок, который мы видим здесь? В частности, то, что вы не открывали файл с помощью fopen () до окончания ресурсоемкой части. В нынешнем виде file_put_contents(), казалось бы, гораздо более простой способ записи в файл.

4. Я думаю, что исправлением этого было бы убедиться, что файл не пустой перед чтением, как я могу это сделать?

5. Попробуйте заблокировать файл перед записью в него. Возможно, существует конфликт из-за нескольких выполняемых скриптов, пытающихся выполнить запись в один и тот же файл.

Ответ №1:

В процедурах кэширования, которые я пишу, я почти всегда проверяю размер файла, поскольку я хочу убедиться, что я не выдаю пустые данные, потому что я полагаюсь на скрипт bash для очистки кэша.

 if(file_exists($cachefile) amp;amp; (filesize($cachefile) > 1024) amp;amp; ((time() - filemtime($cachefile)) < 900))
  

Это предполагает, что ваш выводимый файл кэша имеет размер > 1024 байт, что обычно так и будет, если это что-то относительно большое. Добавление файла блокировки также было бы полезно, как отмечено в комментариях выше, чтобы избежать попыток нескольких процессов выполнить запись в один и тот же файл блокировки.

Ответ №2:

вы можете дважды проверить размер файла с помощью функции filesize (), если он слишком мал, действуйте так, как если бы кэш был старым.

если в файле нет PHP, вы можете либо использовать readfile() из соображений производительности, либо просто отправить файл обратно конечному пользователю.