
# Кешування

Queuety містить рівень кешу, що зменшує кількість запитів до бази даних на часто використовуваних шляхах, як-от перевірки призупинення черги, лічильники обмеження частоти, пошук стану робочого процесу та операції блокування. Кеш автоматично ініціалізується під час виклику `Queuety::init()`.

## Інтерфейс кешу

Усі серверні модулі кешу реалізують `Queuety\Contracts\Cache`:

| Метод | Повертає | Опис |
|---|---|---|
| `get( string $key )` | `mixed` | Отримує значення. Повертає `null`, якщо його не знайдено або строк його дії минув. |
| `set( string $key, mixed $value, int $ttl = 0 )` | `void` | Зберігає значення. TTL 0 означає, що строк дії не обмежений. |
| `delete( string $key )` | `void` | Видаляє значення. |
| `has( string $key )` | `bool` | Перевіряє, чи існує ключ і чи не минув строк його дії. |
| `add( string $key, mixed $value, int $ttl = 0 )` | `bool` | Задає значення, лише якщо ключа ще немає (атомарно). Повертає `true`, якщо значення було задано. |
| `flush()` | `void` | Видаляє всі елементи з кешу. `ApcuCache::flush()` викликає `apcu_clear_cache()`, яка очищає кожен запис APCu на сервері, а не лише записи Queuety. |

## Вбудовані бекенди

### MemoryCache (за замовчуванням)

`Queuety\Cache\MemoryCache` — кеш на основі масиву, окремий для кожного процесу. Елементи зберігаються в масиві PHP і втрачаються після завершення процесу. Це бекенд за замовчуванням, якщо APCu недоступний.

Для нього не потрібні розширення; він добре підходить для розгортань з одним воркером, а кожен процес воркера ізольований від інших.

### ApcuCache

`Queuety\Cache\ApcuCache` використовує розширення APCu для спільної пам’яті між усіма процесами PHP на одному сервері. До всіх ключів автоматично додається префікс `queuety:`, щоб уникнути конфліктів з іншими застосунками.

Для цього бекенду потрібне розширення `php-apcu`. Він спільно використовує записи кешу між воркерами на одному сервері та забезпечує справжню атомарність `add()` за допомогою `apcu_add()`.

## Автоматичне визначення

`Queuety\Cache\CacheFactory` автоматично вибирає найкращий доступний бекенд:

Якщо `apcu_store()` існує, а `apcu_enabled()` повертає `true`, Queuety використовує `ApcuCache`. Інакше він переходить до `MemoryCache`. Це відбувається всередині `Queuety::init()`, тож для поведінки за замовчуванням не потрібна додаткова конфігурація.

## Що кешується

Рівень кешу використовується всередині системи кількома підсистемами:

| Дані | Призначення |
|---|---|
| Стан призупинення черги | Уникає запиту до бази даних на кожній ітерації циклу воркера |
| Лічильники обмеження частоти | Відстежують кількість виконань у пам’яті, а не в базі даних |
| Стан робочого процесу | Зменшує кількість читань під час просування багатоетапного робочого процесу |
| Стан блокування | Прискорює перевірки наявності блокувань для унікальних завдань і проміжного ПЗ mutex |

## Налаштування TTL

Стандартний TTL кешу становить 5 секунд. Він застосовується до стану призупинення черги та лічильників обмеження частоти; читання статусу й стану робочого процесу кешуються на фіксовані 2 секунди, які ця константа не змінює. Перевизначте стандартне значення константою `QUEUETY_CACHE_TTL` у вашому `wp-config.php`:

```php
define( 'QUEUETY_CACHE_TTL', 10 ); // 10 seconds
```

Менший TTL означає частіші запити до бази даних, але актуальніші дані. Більший TTL зменшує навантаження на базу даних, але збільшує ризик застарілих даних. Для більшості розгортань стандартні 5 секунд — вдалий баланс.

## Власний бекенд кешу

Щоб використовувати власний бекенд кешу (Redis, Memcached або будь-який інший), реалізуйте інтерфейс `Contracts\Cache` і викличте `Queuety::set_cache()` перед `Queuety::init()`:

```php
use Queuety\Contracts\Cache;
use Queuety\Queuety;

class RedisCache implements Cache {
    public function get( string $key ): mixed { /* ... */ }
    public function set( string $key, mixed $value, int $ttl = 0 ): void { /* ... */ }
    public function delete( string $key ): void { /* ... */ }
    public function has( string $key ): bool { /* ... */ }
    public function add( string $key, mixed $value, int $ttl = 0 ): bool { /* ... */ }
    public function flush(): void { /* ... */ }
}

// Set the cache before init() so all subsystems use it.
Queuety::set_cache( new RedisCache() );
Queuety::init( $connection );
```

Якщо `set_cache()` викликати перед `init()`, автоматичне визначення фабрики буде повністю пропущено й використовуватиметься ваш власний бекенд.

## Доступ до кешу

Отримати активний екземпляр кешу можна будь-коли:

```php
$cache = Queuety::cache();

$cache->set( 'my_key', 'my_value', 60 );
$value = $cache->get( 'my_key' );
```

Це повертає поточний активний бекенд (MemoryCache, ApcuCache або вашу власну реалізацію).
