
# Armazenamento em cache

Queuety inclui uma camada de cache que reduz consultas ao banco de dados em caminhos críticos, como verificações de pausa da fila, contadores de limites de taxa, consultas ao estado do fluxo de trabalho e operações de bloqueio. O cache é inicializado automaticamente quando você chama `Queuety::init()`.

## Interface de cache

Todos os backends de cache implementam `Queuety\Contracts\Cache`:

| Método | Retorna | Descrição |
|---|---|---|
| `get( string $key )` | `mixed` | Recupera um valor. Retorna `null` se não for encontrado ou tiver expirado. |
| `set( string $key, mixed $value, int $ttl = 0 )` | `void` | Armazena um valor. TTL igual a 0 significa que não expira. |
| `delete( string $key )` | `void` | Remove um valor. |
| `has( string $key )` | `bool` | Verifica se uma chave existe e não expirou. |
| `add( string $key, mixed $value, int $ttl = 0 )` | `bool` | Define um valor somente se a chave ainda não existir (atômico). Retorna `true` se o valor for definido. |
| `flush()` | `void` | Remove todos os itens do cache. `ApcuCache::flush()` chama `apcu_clear_cache()`, que limpa todas as entradas do APCu no servidor, não apenas as de Queuety. |

## Backends integrados

### MemoryCache (padrão)

`Queuety\Cache\MemoryCache` é um cache por processo baseado em array. Os itens são armazenados em um array PHP e perdidos quando o processo é encerrado. Esse é o backend padrão quando o APCu não está disponível.

Não exige extensões, funciona bem em implantações com um único processo de trabalho e mantém cada processo isolado dos demais.

### ApcuCache

`Queuety\Cache\ApcuCache` usa a extensão APCu para compartilhar memória entre todos os processos PHP no mesmo servidor. Todas as chaves recebem automaticamente o prefixo `queuety:` para evitar conflitos com outros aplicativos.

Este backend requer a extensão `php-apcu`, compartilha entradas de cache entre workers no mesmo servidor e torna `add()` realmente atômico por meio de `apcu_add()`.

## Detecção automática

`Queuety\Cache\CacheFactory` escolhe automaticamente o melhor backend disponível:

Se `apcu_store()` existir e `apcu_enabled()` retornar `true`, Queuety usará `ApcuCache`. Caso contrário, usará `MemoryCache`. Isso acontece dentro de `Queuety::init()`, então o comportamento padrão não requer configuração adicional.

## O que é armazenado em cache

A camada de cache é usada internamente por vários subsistemas:

| Dados | Finalidade |
|---|---|
| Estado de pausa da fila | Evita uma consulta ao banco de dados a cada iteração do loop do worker |
| Contadores de limite de taxa | Registra as contagens de execução na memória em vez do banco de dados |
| Estado do workflow | Reduz as leituras durante o avanço de workflows com várias etapas |
| Estado do bloqueio | Acelera as verificações de existência de bloqueios para jobs únicos e o middleware de mutex |

## Configuração do TTL

O TTL de cache padrão é de 5 segundos. Ele se aplica ao estado de pausa da fila e aos contadores de limite de taxa; as leituras de status e estado do workflow ficam em cache por 2 segundos fixos, valor que a constante não altera. Substitua o padrão pela constante `QUEUETY_CACHE_TTL` no seu `wp-config.php`:

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

Um TTL menor significa consultas mais frequentes ao banco de dados, mas dados mais atualizados. Um TTL maior reduz a carga no banco de dados, mas torna os dados menos recentes. Para a maioria das implantações, o padrão de 5 segundos oferece um bom equilíbrio.

## Backend de cache personalizado

Para usar um backend de cache personalizado (Redis, Memcached ou qualquer outro), implemente a interface `Contracts\Cache` e chame `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 );
```

Se `set_cache()` for chamado antes de `init()`, a detecção automática da factory será ignorada por completo e seu backend personalizado será usado.

## Acessar o cache

Recupere a instância de cache ativa a qualquer momento:

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

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

Isso retorna o backend que estiver ativo no momento (MemoryCache, ApcuCache ou sua implementação personalizada).
