PHP code example of hikuroshi / rate-budget
1. Go to this page and download the library: Download hikuroshi/rate-budget library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
hikuroshi / rate-budget example snippets
use Hikuroshi\RateBudget\Quota;
$quota = new Quota();
$key = ['id' => 'key-a', 'rpm' => 15, 'tpm' => 250_000, 'rpd' => 500];
$reserved = $quota->reserve('scope:123', $key, ['tokens' => 800]);
if (! $reserved->ok) {
throw new RuntimeException("Quota blocked: {$reserved->reason}");
}
try {
$response = callProvider($reserved->key);
$quota->commit($reserved->hold, [
'tokens' => $response->usage->totalTokens,
]);
} catch (Throwable $error) {
$quota->rollback($reserved->hold);
throw $error;
}
use Hikuroshi\RateBudget\Quota;
$quota = new Quota(['thresholdPct' => 90]);
$keys = [
['id' => 'key-a', 'rpm' => 15, 'tpm' => 250_000, 'rpd' => 500, 'priority' => 10],
['id' => 'key-b', 'rpm' => 15, 'tpm' => 250_000, 'rpd' => 500, 'priority' => 5],
];
$reserved = $quota->reserve('tenant:acme', $keys, ['tokens' => 2_400]);
if (! $reserved->ok) {
if ($reserved->waitMs !== null) {
queueForLater($reserved->waitMs);
return;
}
throw new RuntimeException("No quota key available: {$reserved->reason}");
}
$response = callProvider($reserved->key);
$quota->commit($reserved->hold, [
'tokens' => $response->usage->totalTokens,
]);
use Hikuroshi\RateBudget\MemoryStore;
use Hikuroshi\RateBudget\Quota;
$quota = new Quota([
'store' => new MemoryStore(),
'estimate' => static fn (array $req): int => $req['inputTokens'] + $req['maxOutputTokens'],
'windowMs' => 60_000,
'bufferMs' => 1_000,
'thresholdPct' => 90,
]);
$single = $quota->reserve('tenant:acme', $key, ['tokens' => 1_500]);
$result = $quota->reserve('tenant:acme', $keys, ['tokens' => 1_500]);
$result->ok; // true
$result->key; // selected key, preserving extra fields
$result->hold; // Hold object for commit/rollback
$result->tokens; // estimated tokens
$result->waitMs; // 0
$result->checks; // list<KeyCheck>
$result->ok; // false
$result->reason; // "rpm", "tpm", "rpd", "off", or "no_key"
$result->waitMs; // int|null
$result->tokens; // estimated tokens
$result->checks; // list<KeyCheck>
$quota->commit($reserved->hold, ['tokens' => $actualTokens]);
$quota->rollback($reserved->hold);
$single = $quota->check('workspace:42', $key, ['tokens' => 800]);
$decision = $quota->check('workspace:42', $keys, ['tokens' => 800]);
$key = [
'id' => 'key-a',
'rpm' => 15,
'tpm' => 250_000,
'rpd' => 500,
'priority' => 10,
'enabled' => true,
];
use Hikuroshi\RateBudget\QuotaStore;
final class DatabaseQuotaStore implements QuotaStore
{
public function mutate(string $scope, callable $fn): mixed
{
return DB::transaction(function () use ($scope, $fn) {
$state = DB::table('quota_states')
->where('scope', $scope)
->lockForUpdate()
->value('state');
$state = $state ? json_decode($state, true) : ['keys' => []];
$result = $fn($state);
DB::table('quota_states')->updateOrInsert(
['scope' => $scope],
['state' => json_encode($state)]
);
return $result;
});
}
}
use const Hikuroshi\RateBudget\BUFFER_MS;
use const Hikuroshi\RateBudget\THRESHOLD_PCT;
use const Hikuroshi\RateBudget\WINDOW_MS;
use function Hikuroshi\RateBudget\cooldownMs;
use function Hikuroshi\RateBudget\dailyCap;
use function Hikuroshi\RateBudget\tokenWaitMs;
cooldownMs(rpm: 15);
dailyCap(rpd: 500, thresholdPct: 90);
tokenWaitMs(
used: 2_000,
tokens: 800,
limit: 10_000,
hits: [['id' => 'hit-1', 'at' => time() * 1000, 'tokens' => 2_000]],
now: time() * 1000,
);
bash
composer dump-autoload
composer check
composer test