
# Limitarea ratei

Queuety acceptă limitarea ratei per handler pentru a preveni suprasolicitarea API-urilor externe sau a altor resurse limitate. Când un handler își atinge limita, workerii lasă sarcinile în așteptare și le preiau din nou când fereastra permite.

## Setarea unei limite de rată

Aplicați o limită de rată la lansarea unei sarcini:

```php
use Queuety\Queuety;

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

Cele două argumente sunt:
1. `$max` - Numărul maxim de execuții permise în interval
2. `$window` - Durata intervalului în secunde

O limită setată la lansare este înregistrată numai în procesul PHP care lansează sarcina. Un worker care rulează într-un proces separat, precum `wp queuety work`, nu o vede; prin urmare, setați limitele care trebuie respectate între procese în metoda `config()` a handlerului, după cum se arată mai jos ([#3](https://github.com/inline0/queuety/issues/3)).

## Limite de rată la nivel de handler

Setați limitele de rată în metoda `config()` a handlerului pentru a le aplica fiecărei lansări:

```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
        ];
    }
}
```

## Cum funcționează

Limitele de rată sunt urmărite per nume de handler. După preluarea unei sarcini, workerul înregistrează limita handlerului (din `config()`) și verifică limitatorul de rată. Dacă handlerul și-a atins limita, workerul pune sarcina imediat înapoi în `pending`, fără întârziere și fără să consume o încercare, apoi așteaptă `QUEUETY_WORKER_SLEEP` secunde înainte de următoarea verificare. În schimb, un worker pornit cu `--once` se oprește.

Fiecare worker păstrează un contor în memorie și îl actualizează la fiecare 5 secunde din tabelul `queuety_logs`, numărând înregistrările de jurnal `completed` pentru handler în ultimele `$window` secunde. Deoarece numărul provine din tabelul de jurnale partajat (și din memoria cache partajată, dacă este configurată), limitele la nivel de handler se aplică tuturor proceselor worker, nu doar unui singur worker. Execuțiile eșuate nu se contabilizează pentru limită.

## Acces programatic

Accesați direct limitatorul de rată:

```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()` și `is_limited()` acționează asupra limitatorului din procesul PHP curent. Înregistrarea unei limite aici nu schimbă limita aplicată de un worker care rulează separat.

## Cazuri de utilizare

- **Limite pentru API externe.** Potriviți limita de rată cu cota API (e.g., 60 RPM pentru OpenAI).
- **Limitarea e-mailurilor.** Împiedicați trimiterea prea multor e-mailuri într-un interval scurt.
- **Protecția resurselor.** Limitați handlerii care solicită intens procesorul, pentru a nu împiedica rularea altor sarcini.
