
# Obmedzovanie frekvencie

Queuety podporuje obmedzovanie frekvencie pre jednotlivé obslužné rutiny, aby sa nepreťažili externé API alebo iné obmedzené zdroje. Keď obslužná rutina dosiahne limit, pracovníci ponechajú jej úlohy vo fronte a znovu ich prevezmú, keď sa v časovom okne uvoľní kapacita.

## Nastavenie limitu frekvencie

Nastavte limit frekvencie pri odosielaní úlohy:

```php
use Queuety\Queuety;

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

Dva argumenty znamenajú:
1. `$max` – maximálny počet vykonaní povolených v časovom okne
2. `$window` – dĺžka časového okna v sekundách

Limit nastavený pri odoslaní sa zaregistruje iba v procese PHP, ktorý úlohu odosiela. Pracovník bežiaci v samostatnom procese, napríklad `wp queuety work`, ho nevidí, preto limity platné naprieč procesmi nastavte v metóde `config()` obslužnej rutiny, ako je uvedené nižšie ([#3](https://github.com/inline0/queuety/issues/3)).

## Limity frekvencie na úrovni obslužnej rutiny

Nastavte limity frekvencie v metóde `config()` obslužnej rutiny, aby platili pre každé odoslanie:

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

## Ako to funguje

Limity frekvencie sa sledujú podľa názvu obslužnej rutiny. Po prevzatí úlohy pracovník zaregistruje limit rutiny (z jej `config()`) a skontroluje obmedzovač frekvencie. Ak rutina dosiahla svoj limit, pracovník úlohu okamžite vráti do `pending` bez oneskorenia a spotrebovania pokusu, potom pred ďalším zisťovaním čaká `QUEUETY_WORKER_SLEEP` sekúnd. Pracovník spustený s `--once` namiesto toho skončí.

Každý pracovník uchováva počítadlo v pamäti a každých 5 sekúnd ho obnovuje z tabuľky `queuety_logs`; počíta záznamy protokolu `completed` pre danú obslužnú rutinu za posledných `$window` sekúnd. Keďže počet sa získava zo zdieľanej tabuľky protokolov (a zo zdieľanej vyrovnávacej pamäte, ak je nastavená), limity na úrovni obslužnej rutiny platia naprieč všetkými procesmi pracovníkov, nielen v jednom pracovníkovi. Neúspešné vykonania sa do limitu nezapočítavajú.

## Programový prístup

Pristúpte k obmedzovaču frekvencie priamo:

```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()` a `is_limited()` pracujú s obmedzovačom v aktuálnom procese PHP. Registrácia limitu tu nemení pravidlá uplatňované samostatne spusteným pracovníkom.

## Prípady použitia

- **Limity externých API.** Nastavte limit frekvencie podľa kvóty služby API (napr. e.g, 60 RPM služby OpenAI).
- **Obmedzenie odosielania e-mailov.** Zabráňte odoslaniu priveľa e-mailov v krátkom čase.
- **Ochrana zdrojov.** Obmedzte obslužné rutiny náročné na procesor, aby neblokovali ostatné úlohy.
