
# Hastighetsbegränsning

Queuety stöder hastighetsbegränsning per hanterare för att förhindra överbelastning av externa API:er eller andra begränsade resurser. När en hanterare har nått sin gräns lämnar arbetarna dess jobb väntande och hämtar dem igen när det finns utrymme i tidsfönstret.

## Ange en hastighetsgräns

Tillämpa en hastighetsgräns när ett jobb skickas:

```php
use Queuety\Queuety;

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

Argumenten är:
1. `$max` – Högsta antal körningar som tillåts under tidsfönstret
2. `$window` – Tidsfönstrets längd i sekunder

En gräns som anges när jobbet skickas registreras endast i processen PHP som skickar jobbet. En arbetare som körs i en separat process, till exempel `wp queuety work`, ser den inte. Ange därför gränser som ska gälla mellan processer i hanterarens `config()`, som visas nedan ([#3](https://github.com/inline0/queuety/issues/3)).

## Hastighetsgränser på hanterarnivå

Ange hastighetsgränser i hanterarens metod `config()` så att de tillämpas för varje jobb som skickas:

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

## Så fungerar det

Hastighetsgränser följs per hanterarnamn. När arbetaren har hämtat ett jobb registrerar den hanterarens gräns (från dess `config()`) och kontrollerar hastighetsbegränsaren. Om hanteraren har nått sin gräns lägger arbetaren omedelbart tillbaka jobbet i `pending` utan fördröjning och utan att förbruka ett försök. Därefter väntar den i `QUEUETY_WORKER_SLEEP` sekunder innan den kontrollerar igen. En arbetare som startats med `--once` avslutas i stället.

Varje arbetare har en räknare i minnet och uppdaterar den var femte sekund från tabellen `queuety_logs`, genom att räkna `completed`-loggposter för hanteraren under de senaste `$window` sekunderna. Eftersom räknaren använder den delade loggtabellen (och den delade cachen, om en sådan har konfigurerats) gäller gränser på hanterarnivå för alla arbetarprocesser, inte bara en enskild arbetare. Misslyckade körningar räknas inte mot gränsen.

## Programmatisk åtkomst

Kom åt hastighetsbegränsaren direkt:

```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()` och `is_limited()` använder begränsaren i den aktuella processen PHP. En gräns som registreras här påverkar inte vad en separat arbetare tillämpar.

## Användningsområden

- **Externa API-gränser.** Anpassa hastighetsgränsen efter API-kvoten (e.gexempelvis OpenAI: 60 RPM).
- **E-postbegränsning.** Förhindra att för många e-postmeddelanden skickas under ett kort tidsintervall.
- **Resursskydd.** Begränsa processorkrävande hanterare för att hindra dem från att svälta ut andra jobb.
