Пример #1
0
 public function hasAll(array $keys)
 {
     return array_has_all_keys($keys, $this->data);
 }
Пример #2
0
 public function getFromCache($id, $group, $REQUIRED_KEYS = null, $sign = null)
 {
     $cacheId = $this->localCacheKey($id, $group);
     //Сначала ищем в локальном хранилище
     if ($this->CACHE->has($cacheId)) {
         $CACHED = $this->CACHE->get($cacheId);
         if ($CACHED['sign'] == $sign) {
             $this->LOGGER->info("Информация по ключу '{$cacheId}' найдена в локальном кеше");
             return $CACHED['data'];
         } else {
             $this->LOGGER->info("Информация по ключу '{$cacheId}' найдена в локальном кеше, но старая и новая подписи не совпадают: [{}]!=[{}]. Чистим...", $CACHED['sign'], $sign);
             $this->CACHE->remove($cacheId);
             $this->CACHELITE->remove($id, $group);
             return null;
         }
     }
     /*
      * Самое интересное и спорное место всей реализации.
      * Нам нужно отслеживать свежесть кешей. Сами по себе они сбрасываются через опередённое время (время жизни кеша).
      * Но это время достаточно велико и, если мы сейчас, например, правим код, то нам некогда ждать, пока всё само сабой обновится.
      * 
      * Кеши валидируются через свои, so called, "подписи".
      * Например - структура проекта (строка навигации) зависит от кол-ва постов в каждом разделе, но при этом если какой-либо пост изменится, то
      * на подпись кеша для навигации это никак не повлияет, а ведь в посте мог измениться анонс, например.
      * 
      * Всё крутится вокруг изменения сущностей фолдингов. При изменении сущности будет сброшен кеш, который от этого фолдинга зависит.
      * Весь вопрос в том - как отслеживать эти изменения?.. Единственное решение - пробегать по всем фолдингам и выполнять checkAllEntityChanged.
      * Решение это довольно дорогостоящее. Даже если сущность не изменилась и кеш не будет перестроен, мы вынуждены выполнить очень много действий.
      * 
      * Есть два варинта для обеспечения "свежести" кешей:
      * 
      * Вариант №1.
      * Каждый раз при запросе кеша выполнять checkAllEntityChanged для фолдингов, от которых зависит запрашеваемая группа кешей.
      * Это нам ВСЕГДА обеспечит свежесть всех кешей, но данная операция является довольно тяжёлой.
      * 
      * Вариант №2.
      * Выполнять проверку checkAllEntityChanged для всех фолдингов, но так как это довольно дорого - делать это не каждый раз, а с определённой периодичностью.
      * Это также обеспечивает свежесть кешей, но операция - очень тяжёлая, поэтому её нельзя выполнять каждый раз.
      * В идеале её вообще должен выполнять внешний процесс, запускаемый раз в EXTERNAL_PROCESS_CALL_DELAY минут.
      * Будем эмулировать его работу посредством класса ExternalProcess.
      * В продакшене будет работать второй вариант - там частота обновлений кешей не так важна.
      */
     $this->validateGroup($group);
     PsProfiler::inst(__CLASS__)->start('LOAD from cache');
     $CACHED = $this->CACHELITE->get($id, $group);
     PsProfiler::inst(__CLASS__)->stop();
     if (!$CACHED) {
         $this->LOGGER->info("Информация по ключу '{$cacheId}' не найдена в кеше");
         return null;
     }
     if (!is_array($CACHED)) {
         $this->LOGGER->info("Информация по ключу '{$cacheId}' найдена в хранилище, но не является массивом. Чистим...");
         $this->CACHELITE->remove($id, $group);
         return null;
     }
     if (!array_has_all_keys(array('data', 'sign'), $CACHED)) {
         $this->LOGGER->info("Информация по ключу '{$cacheId}' найдена в хранилище, но отсутствует параметр sign или data. Чистим...");
         $this->CACHELITE->remove($id, $group);
         return null;
     }
     if ($CACHED['sign'] != $sign) {
         $this->LOGGER->info("Информация по ключу '{$cacheId}' найдена в хранилище, но старая и новая подписи не совпадают: [{}]!=[{}]. Чистим...", $CACHED['sign'], $sign);
         $this->CACHELITE->remove($id, $group);
         return null;
     }
     $MUST_BE_ARRAY = is_array($REQUIRED_KEYS);
     $REQUIRED_KEYS = to_array($REQUIRED_KEYS);
     if ($MUST_BE_ARRAY || !empty($REQUIRED_KEYS)) {
         //Если нам переданы ключи для проверки, значит необходимо убедиться, что сами данные являются массивом
         if (!is_array($CACHED['data'])) {
             $this->LOGGER->info("Информация по ключу '{$cacheId}' найдена в хранилище, но не является массивом. Чистим...");
             $this->CACHELITE->remove($id, $group);
             return null;
         }
         foreach ($REQUIRED_KEYS as $key) {
             if (!array_key_exists($key, $CACHED['data'])) {
                 $this->LOGGER->info("Информация по ключу '{$cacheId}' найдена, но в данных отсутствует обязательный ключ [{$key}]. Чистим...");
                 $this->CACHELITE->remove($id, $group);
                 return null;
             }
         }
     }
     $this->LOGGER->info("Информация по ключу '{$cacheId}' найдена в хранилище");
     //Перенесём данные в локальный кеш для быстрого доступа
     return array_get_value('data', $this->CACHE->set($cacheId, $CACHED));
 }