
# Almacenamiento en caché

Queuety incluye una capa de caché que reduce las consultas a la base de datos en rutas críticas, como las comprobaciones de pausas de cola, los contadores de límites de velocidad, las consultas del estado del flujo de trabajo y las operaciones de bloqueo. La caché se inicializa automáticamente al llamar a `Queuety::init()`.

## Interfaz de caché

Todos los backends de caché implementan `Queuety\Contracts\Cache`:

| Método | Devuelve | Descripción |
|---|---|---|
| `get( string $key )` | `mixed` | Recupera un valor. Devuelve `null` si no se encuentra o ha caducado. |
| `set( string $key, mixed $value, int $ttl = 0 )` | `void` | Almacena un valor. Un TTL de 0 significa que no caduca. |
| `delete( string $key )` | `void` | Elimina un valor. |
| `has( string $key )` | `bool` | Comprueba si una clave existe y no ha caducado. |
| `add( string $key, mixed $value, int $ttl = 0 )` | `bool` | Establece un valor solo si la clave aún no existe (de forma atómica). Devuelve `true` si se estableció el valor. |
| `flush()` | `void` | Elimina todos los elementos de la caché. `ApcuCache::flush()` llama a `apcu_clear_cache()`, que borra todas las entradas de APCu del servidor, no solo las de Queuety. |

## Backends integrados

### MemoryCache (predeterminado)

`Queuety\Cache\MemoryCache` es una caché por proceso respaldada por una matriz. Los elementos se almacenan en una matriz PHP y se pierden cuando termina el proceso. Es el backend predeterminado cuando APCu no está disponible.

No requiere extensiones, funciona bien en implementaciones con un solo proceso de trabajo y mantiene aislado cada proceso de trabajo de los demás.

### ApcuCache

`Queuety\Cache\ApcuCache` usa la extensión APCu para compartir memoria entre todos los procesos PHP del mismo servidor. Todas las claves llevan automáticamente el prefijo `queuety:` para evitar colisiones con otras aplicaciones.

Este backend requiere la extensión `php-apcu`, comparte entradas de caché entre los procesos de trabajo del mismo servidor y hace que `add()` sea realmente atómico mediante `apcu_add()`.

## Detección automática

`Queuety\Cache\CacheFactory` selecciona automáticamente el mejor backend disponible:

Si `apcu_store()` existe y `apcu_enabled()` devuelve `true`, Queuety usa `ApcuCache`. De lo contrario, recurre a `MemoryCache`. Esto ocurre dentro de `Queuety::init()`, así que el comportamiento predeterminado no requiere configuración adicional.

## Qué se almacena en caché

Varios subsistemas usan internamente la capa de caché:

| Datos | Propósito |
|---|---|
| Estado de pausa de la cola | Evita una consulta a la base de datos en cada iteración del proceso de trabajo |
| Contadores de límites de velocidad | Registra en memoria los recuentos de ejecución en lugar de hacerlo en la base de datos |
| Estado del flujo de trabajo | Reduce las lecturas durante el avance de flujos de trabajo con varios pasos |
| Estado del bloqueo | Acelera las comprobaciones de existencia de bloqueos para trabajos únicos y middleware de exclusión mutua |

## Configuración del TTL

El TTL predeterminado de la caché es de 5 segundos. Se aplica al estado de pausa de la cola y a los contadores de límites de velocidad; las lecturas del estado del flujo de trabajo se almacenan en caché durante 2 segundos fijos, que la constante no modifica. Anule el valor predeterminado con la constante `QUEUETY_CACHE_TTL` en su `wp-config.php`:

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

Un TTL más bajo implica consultas más frecuentes a la base de datos, pero datos más recientes. Un TTL más alto reduce la carga de la base de datos, pero hace que los datos puedan estar más desactualizados. Para la mayoría de las implementaciones, el valor predeterminado de 5 segundos ofrece un buen equilibrio.

## Backend de caché personalizado

Para usar un backend de caché personalizado (Redis, Memcached o cualquier otro), implemente la interfaz `Contracts\Cache` y llame a `Queuety::set_cache()` antes de `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 se llama a `set_cache()` antes de `init()`, se omite por completo la detección automática de la fábrica y se usa su backend personalizado.

## Acceder a la caché

Recupere la instancia de caché activa en cualquier momento:

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

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

Esto devuelve el backend que esté activo en ese momento (MemoryCache, ApcuCache o su implementación personalizada).
