レート制限
Queuetyは、外部APIやその他の制約があるリソースへの過負荷を防ぐため、ハンドラーごとのレート制限に対応しています。ハンドラーが上限に達すると、ワーカーはそのジョブを保留し、ウィンドウに空きができたら再び取得します。
レート制限の設定
ジョブのディスパッチ時にレート制限を適用します。
use Queuety\Queuety;
Queuety::dispatch( 'call_openai', $payload )
->rate_limit( 10, 60 ); // max 10 executions per 60 seconds
引数は次の2つです。
$max- ウィンドウ内で許可される実行の最大数$window- ウィンドウの時間(秒)
ディスパッチ時の上限は、ジョブをディスパッチするPHPプロセスにのみ登録されます。wp queuety workのように別プロセスで動作するワーカーからは見えないため、プロセス間で適用する上限は、以下のようにハンドラーのconfig()に設定してください(#3)。
ハンドラー単位のレート制限
ハンドラーのconfig()メソッドにレート制限を設定すると、すべてのディスパッチに適用されます。
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
];
}
}
仕組み
レート制限はハンドラー名ごとに追跡されます。ジョブを取得した後、ワーカーはハンドラーの上限(config()から取得)を登録し、レートリミッターを確認します。上限に達している場合、ワーカーは遅延も試行回数の消費もなく、ジョブをpendingに戻してからQUEUETY_WORKER_SLEEP秒間待機し、再度ポーリングします。--onceを指定して起動したワーカーは、代わりに終了します。
各ワーカーはメモリ内カウンターを保持し、5秒ごとにqueuety_logsテーブルから更新します。このカウンターは、過去$window秒間におけるそのハンドラーのcompletedログエントリー数を数えます。カウントは共有ログテーブル(および設定されている場合は共有キャッシュ)から取得するため、ハンドラー単位の制限は1つのワーカー内だけでなく、すべてのワーカープロセスに適用されます。失敗した実行は上限に含まれません。
プログラムからのアクセス
レートリミッターに直接アクセスします。
$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()とis_limited()は、現在のPHPプロセス内のリミッターに作用します。ここで上限を登録しても、別途実行中のワーカーが適用する制限は変わりません。
活用例
- 外部APIの制限。 レート制限をAPIのクォータ(e.g例:OpenAIの60 RPM)に合わせます。
- メール送信の抑制。 短時間に大量のメールを送信するのを防ぎます。
- リソースの保護。 CPU負荷の高いハンドラーを制限し、他のジョブが滞らないようにします。