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