
# Limitazione della frequenza

Queuety supporta la limitazione della frequenza per handler, per evitare di sovraccaricare API esterne o altre risorse limitate. Quando un handler raggiunge il limite, i worker lasciano i suoi processi in attesa e li riprendono quando la finestra consente nuove esecuzioni.

## Impostazione di un limite di frequenza

Applica un limite di frequenza quando invii un processo:

```php
use Queuety\Queuety;

Queuety::dispatch( 'call_openai', $payload )
    ->rate_limit( 10, 60 ); // max 10 executions per 60 seconds
```

I due argomenti sono:
1. `$max` - Numero massimo di esecuzioni consentite nella finestra
2. `$window` - Durata della finestra in secondi

Un limite impostato al momento dell'invio viene registrato solo nel processo PHP che invia il job. Un worker in esecuzione in un processo separato, come `wp queuety work`, non lo vede; imposta quindi nel `config()` dell'handler i limiti che devono valere tra processi, come mostrato di seguito ([#3](https://github.com/inline0/queuety/issues/3)).

## Limiti di frequenza a livello di handler

Imposta i limiti di frequenza nel metodo `config()` dell'handler, così si applicano a ogni invio:

```php
use Queuety\Handler;

class CallOpenAIHandler implements Handler {
    public function handle( array $payload ): void {
        // Call the API...
    }

    public function config(): array {
        return [
            'rate_limit' => [ 60, 60 ], // 60 requests per minute
        ];
    }
}
```

## Come funziona

I limiti di frequenza vengono monitorati per nome dell'handler. Dopo aver acquisito un processo, il worker registra il limite dell'handler (dal suo `config()`) e controlla il limitatore di frequenza. Se l'handler ha raggiunto il limite, il worker rimette subito il processo in `pending`, senza ritardo e senza consumare un tentativo, poi attende `QUEUETY_WORKER_SLEEP` secondi prima di interrogare di nuovo la coda. Un worker avviato con `--once` termina invece.

Ogni worker mantiene un contatore in memoria e lo aggiorna ogni 5 secondi dalla tabella `queuety_logs`, contando le voci di log `completed` dell'handler negli ultimi `$window` secondi. Poiché il conteggio proviene dalla tabella dei log condivisa (e dalla cache condivisa, se configurata), i limiti a livello di handler vengono applicati a tutti i processi worker, non solo a un singolo worker. Le esecuzioni non riuscite non vengono conteggiate nel limite.

## Accesso programmatico

Accedi direttamente al limitatore di frequenza:

```php
$limiter = Queuety::rate_limiter();

// Register a rate limit
$limiter->register( 'call_openai', 60, 60 );

// Check whether a handler has reached its limit
$limited = $limiter->is_limited( 'call_openai' ); // true while the limit is reached

// Seconds until the current window resets
$wait = $limiter->time_until_available( 'call_openai' );
```

`register()` e `is_limited()` agiscono sul limitatore nel processo PHP corrente. Registrare qui un limite non modifica ciò che applica un worker in esecuzione separata.

## Casi d'uso

- **Limiti delle API esterne API.** Adegua il limite di frequenza alla quota di API (e.g., 60 RPM di OpenAI).
- **Limitazione delle email.** Evita di inviare troppe email in un breve intervallo.
- **Protezione delle risorse.** Limita gli handler che richiedono molta CPU per evitare che sottraggano risorse agli altri processi.
