
# Nopeusrajoitukset

Queuety tukee käsittelijäkohtaista nopeusrajoitusta ulkoisten rajapintojen tai muiden rajallisten resurssien ylikuormituksen estämiseksi. Kun käsittelijä saavuttaa rajansa, työntekijät jättävät sen työt odottamaan ja ottavat ne käsittelyyn uudelleen, kun aikaikkunassa on tilaa.

## Nopeusrajoituksen määrittäminen

Aseta nopeusrajoitus työtä lähettäessä:

```php
use Queuety\Queuety;

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

Kaksi argumenttia ovat:
1. `$max` - Suoritusten enimmäismäärä aikaikkunassa
2. `$window` - Aikaikkunan kesto sekunteina

Lähetyshetkellä asetettu rajoitus rekisteröidään vain työn lähettävän PHP-prosessin käyttöön. Erillisessä prosessissa, kuten `wp queuety work`, käynnissä oleva työntekijä ei näe sitä. Aseta siis prosessien välillä voimassa olevat rajoitukset käsittelijän `config()`-metodissa, kuten alla näytetään ([#3](https://github.com/inline0/queuety/issues/3)).

## Käsittelijätason nopeusrajoitukset

Aseta nopeusrajoitukset käsittelijän `config()`-metodissa, jotta ne koskevat jokaista lähetystä:

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

## Näin se toimii

Nopeusrajoituksia seurataan käsittelijän nimen mukaan. Otettuaan työn käsiteltäväksi työntekijä rekisteröi käsittelijän rajoituksen (sen `config()`-metodista) ja tarkistaa nopeusrajoittimen. Jos käsittelijä on saavuttanut rajansa, työntekijä palauttaa työn välittömästi `pending`-tilaan ilman viivettä ja yritystä kuluttamatta. Sen jälkeen se odottaa `QUEUETY_WORKER_SLEEP` sekuntia ennen seuraavaa kyselyä. `--once`-asetuksella käynnistetty työntekijä sen sijaan päättyy.

Kukin työntekijä pitää muistissa olevaa laskuria ja päivittää sen 5 sekunnin välein `queuety_logs`-taulusta. Laskuri laskee käsittelijän `completed`-lokimerkinnät viimeisten `$window` sekunnin ajalta. Koska määrä lasketaan jaetusta lokitaulusta (ja määritetystä jaetusta välimuistista, jos sellainen on käytössä), käsittelijätason rajoitukset koskevat kaikkia työntekijäprosesseja, eivät vain yhtä työntekijää. Epäonnistuneita suorituksia ei lasketa mukaan rajaan.

## Ohjelmallinen käyttö

Käytä nopeusrajoitinta suoraan:

```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()` ja `is_limited()` käyttävät nykyisen PHP-prosessin rajoitinta. Rajoituksen rekisteröiminen tässä ei muuta erikseen käynnissä olevan työntekijän valvomia rajoituksia.

## Käyttötapaukset

- **Ulkoisten API-palvelujen rajoitukset.** Sovita nopeusrajoitus API-palvelun kiintiöön (e.g., OpenAI-palvelun 60 RPM).
- **Sähköpostin rajoittaminen.** Estä liian monen sähköpostin lähettäminen lyhyessä ajassa.
- **Resurssien suojaaminen.** Rajoita prosessoritehoa kuluttavien käsittelijöiden käyttöä, jotta ne eivät vie kapasiteettia muilta töiltä.
