
# Memorizzazione nella cache

Queuety include un livello di cache che riduce le query al database nei percorsi più frequenti, come i controlli di sospensione delle code, i contatori dei limiti di frequenza, le ricerche dello stato dei workflow e le operazioni sui lock. La cache viene inizializzata automaticamente quando chiamate `Queuety::init()`.

## Interfaccia della cache

Tutti i backend di cache implementano `Queuety\Contracts\Cache`:

| Metodo | Restituisce | Descrizione |
|---|---|---|
| `get( string $key )` | `mixed` | Recupera un valore. Restituisce `null` se non trovato o scaduto. |
| `set( string $key, mixed $value, int $ttl = 0 )` | `void` | Memorizza un valore. Un TTL pari a 0 significa che non scade. |
| `delete( string $key )` | `void` | Rimuove un valore. |
| `has( string $key )` | `bool` | Verifica se una chiave esiste e non è scaduta. |
| `add( string $key, mixed $value, int $ttl = 0 )` | `bool` | Imposta un valore solo se la chiave non esiste già (atomico). Restituisce `true` se il valore è stato impostato. |
| `flush()` | `void` | Rimuove tutti gli elementi dalla cache. `ApcuCache::flush()` chiama `apcu_clear_cache()`, che svuota ogni voce APCu sul server, non solo quelle di Queuety. |

## Backend integrati

### MemoryCache (predefinita)

`Queuety\Cache\MemoryCache` è una cache basata su array e limitata al singolo processo. Gli elementi sono memorizzati in un array PHP e vengono persi alla chiusura del processo. È il backend predefinito quando APCu non è disponibile.

Non richiede estensioni, funziona bene con distribuzioni a singolo worker e mantiene isolato ogni processo worker dagli altri.

### ApcuCache

`Queuety\Cache\ApcuCache` usa l'estensione APCu per condividere la memoria tra tutti i processi PHP sullo stesso server. Tutte le chiavi ricevono automaticamente il prefisso `queuety:` per evitare conflitti con altre applicazioni.

Questo backend richiede l'estensione `php-apcu`, condivide le voci della cache tra i worker sullo stesso server e rende `add()` davvero atomico tramite `apcu_add()`.

## Rilevamento automatico

`Queuety\Cache\CacheFactory` sceglie automaticamente il backend migliore disponibile:

Se `apcu_store()` esiste e `apcu_enabled()` restituisce `true`, Queuety usa `ApcuCache`. In caso contrario, ripiega su `MemoryCache`. Questo avviene all'interno di `Queuety::init()`, quindi il comportamento predefinito non richiede configurazioni aggiuntive.

## Cosa viene memorizzato nella cache

Il livello di cache è usato internamente da diversi sottosistemi:

| Dato | Scopo |
|---|---|
| Stato di pausa della coda | Evita una query al database a ogni iterazione del ciclo del worker |
| Contatori dei limiti di frequenza | Tiene traccia in memoria del numero di esecuzioni invece che nel database |
| Stato del workflow | Riduce le letture durante l'avanzamento dei workflow con più passaggi |
| Stato dei lock | Velocizza il controllo dell'esistenza dei lock per i job univoci e il middleware mutex |

## Configurazione del TTL

Il TTL predefinito della cache è di 5 secondi. Si applica allo stato di pausa della coda e ai contatori dei limiti di frequenza; le letture dello stato e dell'avanzamento del workflow vengono memorizzate nella cache per 2 secondi fissi, che la costante non modifica. Sostituite il valore predefinito con la costante `QUEUETY_CACHE_TTL` nel vostro `wp-config.php`:

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

Un TTL più basso comporta query al database più frequenti, ma dati più aggiornati. Un TTL più alto riduce il carico sul database, ma rende i dati meno aggiornati. Per la maggior parte delle distribuzioni, il valore predefinito di 5 secondi offre un buon equilibrio.

## Backend di cache personalizzato

Per usare un backend di cache personalizzato (Redis, Memcached o qualsiasi altro), implementate l'interfaccia `Contracts\Cache` e chiamate `Queuety::set_cache()` prima di `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()` viene chiamato prima di `init()`, il rilevamento automatico della factory viene saltato del tutto e viene usato il backend personalizzato.

## Accesso alla cache

Recuperate in qualsiasi momento l'istanza di cache attiva:

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

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

Restituisce il backend attualmente attivo (MemoryCache, ApcuCache o la vostra implementazione personalizzata).
