PSR-6: Интерфейс для кэширования

Дата публикации: 2024-01-09
Просмотры: 327

PSR (PHP Standards Recommendations) - это набор рекомендаций по программированию на языке PHP.
Кэширование — это распространенный способ повышения производительности любого проекта, что делает библиотеки кэширования одной из наиболее распространенных функций многих платформ и библиотек. Это привело к тому, что многие библиотеки создают свои собственные библиотеки кэширования с различными уровнями функциональности. Эти различия вынуждают разработчиков изучать несколько систем, которые могут обеспечивать или не обеспечивать необходимую им функциональность. Кроме того, перед самими разработчиками библиотек кэширования стоит выбор между поддержкой лишь ограниченного количества фреймворков или созданием большого количества классов-адаптеров.

PSR-6: Интерфейс для кэширования

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

Цель

Цель PSR-6 — позволить разработчикам создавать библиотеки с поддержкой кэша, которые можно интегрировать в существующие платформы и системы без необходимости специальной разработки.

Определения

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

  • Реализация библиотеки. Эта библиотека отвечает за реализацию этого стандарта для предоставления услуг кэширования любой вызывающей библиотеке. Реализующая библиотека должна предоставлять классы, реализующие интерфейсы Cache\CacheItemPoolInterface и Cache\CacheItemInterface. Реализация библиотек должна поддерживать функциональность минимального TTL, как описано ниже, с точностью до целой секунды.

  • TTL — время жизни (TTL) элемента — это промежуток времени между тем, когда этот элемент хранится, и тем, как он считается устаревшим. TTL обычно определяется целым числом, представляющим время в секундах, или объектом DateInterval.

  • Срок действия (Expiration) — фактическое время, когда элемент устареет. Обычно он рассчитывается путем добавления TTL ко времени хранения объекта, но также может быть явно установлен с помощью объекта DateTime. Элемент с TTL 300 секунд, хранящийся в 1:30:00, будет иметь срок действия 1:35:00. Реализующие библиотеки могут истечь срок действия элемента до запрошенного срока действия, но должны считать элемент просроченным после достижения его срока действия. Если вызывающая библиотека запрашивает сохранение элемента, но не указывает время истечения срока действия или указывает нулевое время истечения срока действия или TTL, реализующая библиотека может использовать настроенную продолжительность по умолчанию. Если продолжительность по умолчанию не установлена, реализующая библиотека должна интерпретировать это как запрос на кэширование элемента навсегда или до тех пор, пока поддерживается базовая реализация.

  • Ключ (Key) — строка, состоящая как минимум из одного символа, которая однозначно идентифицирует кэшированный элемент. Реализующие библиотеки должны поддерживать ключи, состоящие из символов A-Z, a-z, 0-9, _ и . в любом порядке в кодировке UTF-8 и длиной до 64 символов. Реализующие библиотеки могут поддерживать дополнительные символы и кодировки или более длинные длины, но должны поддерживать хотя бы этот минимум. Библиотеки несут ответственность за собственное экранирование строк ключей, но должны иметь возможность возвращать исходную немодифицированную строку ключей. Следующие символы зарезервированы для будущих расширений и не должны поддерживаться реализующими библиотеками: {}()/\@:

  • Попадание (Hit) — попадание в кэш происходит, когда вызывающая библиотека запрашивает элемент по ключу и для этого ключа найдено соответствующее значение, и это значение еще не истекло, а значение не является недопустимым по какой-либо другой причине. Вызывающим библиотекам следует обязательно проверять isHit() во всех вызовах get().

  • Промах (Miss). Промах в кэше является противоположностью попадания в кэш. Промах в кэше происходит, когда вызывающая библиотека запрашивает элемент по ключу и это значение не найдено для этого ключа, или значение было найдено, но срок его действия истек, или значение недействительно по какой-либо другой причине. Значение с истекшим сроком действия всегда должно рассматриваться как промах в кэше.

  • Отложенное (Deferred) — отложенное сохранение в кэше указывает на то, что элемент кэша не может быть немедленно сохранен в пуле. Объект пула может задержать сохранение элемента отложенного кэша, чтобы воспользоваться преимуществами операций массового набора, поддерживаемых некоторыми механизмами хранения. Пул должен гарантировать, что любые элементы отложенного кэша в конечном итоге сохраняются и данные не теряются, и может сохранять их до того, как вызывающая библиотека запросит их сохранение. Когда вызывающая библиотека вызывает метод commit(), все невыполненные отложенные элементы должны быть сохранены. Реализующая библиотека может использовать любую подходящую логику для определения того, когда сохранять отложенные элементы, например деструктор объекта, сохранение всего при save(), проверку тайм-аута или максимального количества элементов или любую другую подходящую логику. Запросы на элемент кэша, который был отложен, должны возвращать отложенный, но еще не сохраненный элемент.

Данные

Реализующие библиотеки должны поддерживать все сериализуемые типы данных PHP, включая:

  • Строки — символьные строки произвольного размера в любой PHP-совместимой кодировке.
  • Целые числа — все целые числа любого размера, поддерживаемые PHP, вплоть до 64-битных знаков.
  • Дробные числа — все числовые значения с плавающей запятой.
  • Логическое значениеtrue и false.
  • Null — фактическое null значение.
  • Массивы — Индексированные, ассоциативные и многомерные массивы произвольной глубины.
  • Объект — любой объект, поддерживающий сериализацию и десериализацию без потерь, например $o == unserialize(serialize($o)). Объекты могут использовать сериализуемый интерфейс PHP, __sleep() или __wakeup() магические методы или аналогичные функции языка, если это необходимо.

Все данные, переданные во реализующую библиотеку, должны быть возвращены точно в том виде, в котором они были переданы. Это включает в себя тип переменной. То есть (string) 5 будет ошибкой, если (int) 5 было числом. Реализации библиотек могут использовать PHP функции serialize() и unserialize() внутри, но это не обязательно. Совместимость с ними просто используется в качестве основы для приемлемых значений объекта.

Если по какой-либо причине невозможно вернуть точное сохраненное значение, реализующие библиотеки должны ответить промахом (miss) в кэше, а не поврежденными данными.

Ключевые понятия

Pool

Пул представляет собой набор элементов в системе кэширования. Пул является логическим хранилищем всех содержащихся в нем элементов. Все кэшируемые элементы извлекаются из пула как объект Item, и все взаимодействие со всей вселенной кэшированных объектов происходит через пул.

Items

Элемент представляет собой одну пару ключ/значение в пуле. Ключ является основным уникальным идентификатором элемента и должен быть неизменяемым. Значение может быть изменено в любое время.

Обработка ошибок

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

Реализующая библиотека должна регистрировать такие ошибки или иным образом сообщать о них администратору, если это необходимо.

Если вызывающая библиотека запрашивает удаление одного или нескольких элементов или очистку пула, это не должно рассматриваться как состояние ошибки, если указанный ключ не существует. Постусловие то же самое (ключ не существует или пул пуст), поэтому условие ошибки отсутствует.

Интерфейсы

CacheItemInterface

CacheItemInterface определяет элемент внутри системы кэширования. Каждый объект Item должен быть связан с определенным ключом, который может быть установлен в соответствии с реализующей системой и обычно передается объектом Cache\CacheItemPoolInterface.

Объект Cache\CacheItemInterface инкапсулирует хранение и извлечение элементов кэша. Каждый из них Cache\CacheItemInterface генерируется объектом Cache\CacheItemPoolInterface, который отвечает за любую необходимую настройку, а также связывает объект с уникальным ключом. Cache\CacheItemInterface объекты должны иметь возможность хранить и извлекать значения PHP любого типа, определенные в разделе «Данные» этого документа.

Вызывающие библиотеки не должны сами создавать экземпляры объектов Item. Их можно запросить только у объекта Pool через getItem() метод. Вызывающие библиотеки не должны предполагать, что элемент, созданный одной реализующей библиотекой, совместим с пулом из другой реализующей библиотеки.

<?php

namespace Psr\Cache;

/**
 * CacheItemInterface defines an interface for interacting with objects inside a cache.
 */
interface CacheItemInterface
{
    /**
     * Returns the key for the current cache item.
     *
     * The key is loaded by the Implementing Library, but should be available to
     * the higher level callers when needed.
     *
     * @return string
     *   The key string for this cache item.
     */
    public function getKey();

    /**
     * Retrieves the value of the item from the cache associated with this object's key.
     *
     * The value returned must be identical to the value originally stored by set().
     *
     * If isHit() returns false, this method MUST return null. Note that null
     * is a legitimate cached value, so the isHit() method SHOULD be used to
     * differentiate between "null value was found" and "no value was found."
     *
     * @return mixed
     *   The value corresponding to this cache item's key, or null if not found.
     */
    public function get();

    /**
     * Confirms if the cache item lookup resulted in a cache hit.
     *
     * Note: This method MUST NOT have a race condition between calling isHit()
     * and calling get().
     *
     * @return bool
     *   True if the request resulted in a cache hit. False otherwise.
     */
    public function isHit();

    /**
     * Sets the value represented by this cache item.
     *
     * The $value argument may be any item that can be serialized by PHP,
     * although the method of serialization is left up to the Implementing
     * Library.
     *
     * @param mixed $value
     *   The serializable value to be stored.
     *
     * @return static
     *   The invoked object.
     */
    public function set($value);

    /**
     * Sets the expiration time for this cache item.
     *
     * @param \DateTimeInterface|null $expiration
     *   The point in time after which the item MUST be considered expired.
     *   If null is passed explicitly, a default value MAY be used. If none is set,
     *   the value should be stored permanently or for as long as the
     *   implementation allows.
     *
     * @return static
     *   The called object.
     */
    public function expiresAt($expiration);

    /**
     * Sets the expiration time for this cache item.
     *
     * @param int|\DateInterval|null $time
     *   The period of time from the present after which the item MUST be considered
     *   expired. An integer parameter is understood to be the time in seconds until
     *   expiration. If null is passed explicitly, a default value MAY be used.
     *   If none is set, the value should be stored permanently or for as long as the
     *   implementation allows.
     *
     * @return static
     *   The called object.
     */
    public function expiresAfter($time);

}

CacheItemPoolInterface

Основная цель Cache\CacheItemPoolInterface — принять ключ из библиотеки вызовов и вернуть связанный объект Cache\CacheItemInterface. Это также основная точка взаимодействия со всей коллекцией кэша. Вся настройка и инициализация пула остается на усмотрение реализующей библиотеки.

<?php

namespace Psr\Cache;

/**
 * CacheItemPoolInterface generates CacheItemInterface objects.
 */
interface CacheItemPoolInterface
{
    /**
     * Returns a Cache Item representing the specified key.
     *
     * This method must always return a CacheItemInterface object, even in case of
     * a cache miss. It MUST NOT return null.
     *
     * @param string $key
     *   The key for which to return the corresponding Cache Item.
     *
     * @throws InvalidArgumentException
     *   If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     *
     * @return CacheItemInterface
     *   The corresponding Cache Item.
     */
    public function getItem($key);

    /**
     * Returns a traversable set of cache items.
     *
     * @param string[] $keys
     *   An indexed array of keys of items to retrieve.
     *
     * @throws InvalidArgumentException
     *   If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     *
     * @return array|\Traversable
     *   A traversable collection of Cache Items keyed by the cache keys of
     *   each item. A Cache item will be returned for each key, even if that
     *   key is not found. However, if no keys are specified then an empty
     *   traversable MUST be returned instead.
     */
    public function getItems(array $keys = array());

    /**
     * Confirms if the cache contains specified cache item.
     *
     * Note: This method MAY avoid retrieving the cached value for performance reasons.
     * This could result in a race condition with CacheItemInterface::get(). To avoid
     * such situation use CacheItemInterface::isHit() instead.
     *
     * @param string $key
     *   The key for which to check existence.
     *
     * @throws InvalidArgumentException
     *   If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     *
     * @return bool
     *   True if item exists in the cache, false otherwise.
     */
    public function hasItem($key);

    /**
     * Deletes all items in the pool.
     *
     * @return bool
     *   True if the pool was successfully cleared. False if there was an error.
     */
    public function clear();

    /**
     * Removes the item from the pool.
     *
     * @param string $key
     *   The key to delete.
     *
     * @throws InvalidArgumentException
     *   If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     *
     * @return bool
     *   True if the item was successfully removed. False if there was an error.
     */
    public function deleteItem($key);

    /**
     * Removes multiple items from the pool.
     *
     * @param string[] $keys
     *   An array of keys that should be removed from the pool.
     *
     * @throws InvalidArgumentException
     *   If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException
     *   MUST be thrown.
     *
     * @return bool
     *   True if the items were successfully removed. False if there was an error.
     */
    public function deleteItems(array $keys);

    /**
     * Persists a cache item immediately.
     *
     * @param CacheItemInterface $item
     *   The cache item to save.
     *
     * @return bool
     *   True if the item was successfully persisted. False if there was an error.
     */
    public function save(CacheItemInterface $item);

    /**
     * Sets a cache item to be persisted later.
     *
     * @param CacheItemInterface $item
     *   The cache item to save.
     *
     * @return bool
     *   False if the item could not be queued or if a commit was attempted and failed. True otherwise.
     */
    public function saveDeferred(CacheItemInterface $item);

    /**
     * Persists any deferred cache items.
     *
     * @return bool
     *   True if all not-yet-saved items were successfully saved or there were none. False otherwise.
     */
    public function commit();
}

CacheException

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

Любое исключение, создаваемое реализующей библиотекой, должно реализовывать этот интерфейс.

<?php

namespace Psr\Cache;

/**
 * Exception interface for all exceptions thrown by an Implementing Library.
 */
interface CacheException
{
}

InvalidArgumentException

<?php

namespace Psr\Cache;

/**
 * Exception interface for invalid cache arguments.
 *
 * Any time an invalid argument is passed into a method it must throw an
 * exception class which implements Psr\Cache\InvalidArgumentException.
 */
interface InvalidArgumentException extends CacheException
{
}

Начиная с версии psr/cache 2.0, приведенные выше интерфейсы были обновлены и добавлены подсказки по типам аргументов. Начиная с версии psr/cache 3.0, приведенные выше интерфейсы были обновлены и добавлены подсказки по типу возвращаемого значения. Ссылки должны array|\Traversable быть заменены на iterable.


Ссылка на источник: https://www.php-fig.org/psr/psr-6/

Поделиться статьей:

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

Авторизуйтесь, для того, чтобы оставить комментарий. Войти на сайт
Подписка на новости
Узнавайте о новых статьях первыми.
Профиль