
# Mise en cache

Queuety inclut une couche de cache qui réduit les requêtes à la base de données sur les chemins critiques, comme les vérifications de mise en pause des files d’attente, les compteurs de limitation de débit, les recherches d’état du workflow et les opérations de verrouillage. Le cache est initialisé automatiquement lorsque vous appelez `Queuety::init()`.

## Interface du cache

Tous les moteurs de cache implémentent `Queuety\Contracts\Cache` :

| Méthode | Valeur renvoyée | Description |
|---|---|---|
| `get( string $key )` | `mixed` | Récupère une valeur. Renvoie `null` si elle est introuvable ou expirée. |
| `set( string $key, mixed $value, int $ttl = 0 )` | `void` | Stocke une valeur. Un TTL de 0 signifie qu’elle n’expire pas. |
| `delete( string $key )` | `void` | Supprime une valeur. |
| `has( string $key )` | `bool` | Vérifie si une clé existe et n’a pas expiré. |
| `add( string $key, mixed $value, int $ttl = 0 )` | `bool` | Définit une valeur uniquement si la clé n’existe pas déjà (atomique). Renvoie `true` si la valeur a été définie. |
| `flush()` | `void` | Supprime tous les éléments du cache. `ApcuCache::flush()` appelle `apcu_clear_cache()`, qui efface toutes les entrées APCu du serveur, et pas seulement celles de Queuety. |

## Moteurs intégrés

### MemoryCache (par défaut)

`Queuety\Cache\MemoryCache` est un cache par processus reposant sur un tableau. Les éléments sont stockés dans un tableau PHP et perdus à la fermeture du processus. C’est le moteur par défaut lorsqu’APCu n’est pas disponible.

Il ne nécessite aucune extension, convient aux déploiements à processus de travail unique et isole chaque processus de travail des autres.

### ApcuCache

`Queuety\Cache\ApcuCache` utilise l’extension APCu pour partager la mémoire entre tous les processus PHP du même serveur. Toutes les clés reçoivent automatiquement le préfixe `queuety:` afin d’éviter les conflits avec d’autres applications.

Ce moteur nécessite l’extension `php-apcu`, partage les entrées de cache entre les processus de travail d’un même serveur et rend `add()` véritablement atomique via `apcu_add()`.

## Détection automatique

`Queuety\Cache\CacheFactory` sélectionne automatiquement le meilleur moteur disponible :

Si `apcu_store()` existe et que `apcu_enabled()` renvoie `true`, Queuety utilise `ApcuCache`. Sinon, il revient à `MemoryCache`. Cela se produit dans `Queuety::init()`, le comportement par défaut ne nécessite donc aucune configuration supplémentaire.

## Données mises en cache

La couche de cache est utilisée en interne par plusieurs sous-systèmes :

| Données | Objectif |
|---|---|
| État de mise en pause de la file d’attente | Évite une requête à la base de données à chaque itération de la boucle du processus de travail |
| Compteurs de limitation de débit | Suit les nombres d’exécutions en mémoire plutôt que dans la base de données |
| État du workflow | Réduit les lectures lors de l’avancement d’un workflow à plusieurs étapes |
| État des verrous | Accélère les vérifications d’existence des verrous pour les tâches uniques et le middleware de mutex |

## Configuration du TTL

Le TTL du cache est de 5 secondes par défaut. Il s’applique à l’état de mise en pause de la file d’attente et aux compteurs de limitation de débit ; les lectures de l’état et du statut du workflow sont mises en cache pendant une durée fixe de 2 secondes, que la constante ne modifie pas. Remplacez la valeur par défaut avec la constante `QUEUETY_CACHE_TTL` dans votre `wp-config.php` :

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

Un TTL plus faible entraîne des requêtes à la base de données plus fréquentes, mais des données plus récentes. Un TTL plus élevé réduit la charge sur la base de données, mais rend les données plus anciennes. Pour la plupart des déploiements, la valeur par défaut de 5 secondes offre un bon équilibre.

## Moteur de cache personnalisé

Pour utiliser un moteur de cache personnalisé (Redis, Memcached ou autre), implémentez l’interface `Contracts\Cache` et appelez `Queuety::set_cache()` avant `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 );
```

Si `set_cache()` est appelé avant `init()`, la détection automatique du moteur est entièrement ignorée et votre moteur personnalisé est utilisé.

## Accéder au cache

Récupérez l’instance du cache actif à tout moment :

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

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

Cela renvoie le moteur actuellement actif (MemoryCache, ApcuCache ou votre implémentation personnalisée).
