
# Sebességkorlátozás

Queuety kezelőnkénti sebességkorlátozást biztosít, hogy megelőzze a külső API-k vagy más korlátozott erőforrások túlterhelését. Ha egy kezelő eléri a korlátját, a workerek függőben hagyják a feladatait, és akkor veszik fel újra őket, amikor az időablakban ismét van hely.

## Sebességkorlát beállítása

Sebességkorlát alkalmazása egy feladat indításakor:

```php
use Queuety\Queuety;

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

A két argumentum:
1. `$max` – Az időablakban engedélyezett végrehajtások maximális száma
2. `$window` – Az időablak hossza másodpercben

A dispatch idején beállított korlátot csak az a PHP folyamat tartja nyilván, amely elindítja a feladatot. Egy külön folyamatban futó worker, például a `wp queuety work`, nem látja ezt, ezért a folyamatok között érvényes korlátokat a kezelő `config()` metódusában állítsa be az alábbiak szerint ([#3](https://github.com/inline0/queuety/issues/3)).

## Kezelőszintű sebességkorlátok

A kezelő `config()` metódusában állítsa be a sebességkorlátokat, hogy minden dispatchre érvényesek legyenek:

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

## Működés

A sebességkorlátokat kezelőnév szerint tartjuk nyilván. Egy feladat átvétele után a worker regisztrálja a kezelő korlátját (a `config()` értékéből), majd ellenőrzi a sebességkorlátozót. Ha a kezelő elérte a korlátját, a worker késleltetés és próbálkozás felhasználása nélkül visszateszi a feladatot a `pending` állapotba, majd `QUEUETY_WORKER_SLEEP` másodpercig vár, mielőtt újra lekérdez. Az `--once` értékkel indított worker ehelyett kilép.

Minden worker memóriában tart egy számlálót, és 5 másodpercenként frissíti a `queuety_logs` táblából. A kezelőhöz tartozó, elmúlt `$window` másodperc `completed` naplóbejegyzéseit számolja. Mivel a számlálás a megosztott naplótáblából (és konfigurált megosztott gyorsítótár esetén abból is) történik, a kezelőszintű korlátok minden workerfolyamatra érvényesek, nem csak egyetlen workerre. A sikertelen végrehajtások nem számítanak bele a korlátba.

## Programozott hozzáférés

A sebességkorlátozó közvetlen elérése:

```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' );
```

A `register()` és a `is_limited()` a jelenlegi PHP folyamat korlátozóján működik. Ha itt regisztrál egy korlátot, az nem módosítja a külön futó worker által érvényesített korlátot.

## Felhasználási esetek

- **Külső API-korlátok.** A sebességkorlátot igazítsa a API kvótájához (e.g., például a OpenAI 60 RPM-es korlátjához).
- **E-mailek korlátozása.** Megakadályozza, hogy rövid idő alatt túl sok e-mailt küldjön.
- **Erőforrásvédelem.** Korlátozza a CPU-igényes kezelőket, hogy ne szorítsák ki a többi feladatot.
