58 lines
1.5 KiB
PHP
58 lines
1.5 KiB
PHP
<?php
|
|
|
|
namespace Msr\LaravelBitunixApi\Support;
|
|
|
|
use Illuminate\Contracts\Cache\Repository;
|
|
use Msr\LaravelBitunixApi\Contracts\RateLimiterContract;
|
|
|
|
class CacheRateLimiter implements RateLimiterContract
|
|
{
|
|
public function __construct(
|
|
protected Repository $cache,
|
|
) {
|
|
}
|
|
|
|
public function throttle(
|
|
string $bucket,
|
|
string $identity,
|
|
int $maxRequests,
|
|
float $perSeconds
|
|
): void {
|
|
if ($maxRequests <= 0 || $perSeconds <= 0) {
|
|
return;
|
|
}
|
|
|
|
$cacheKey = $this->makeCacheKey($bucket, $identity);
|
|
$minIntervalMicroseconds = (int) (($perSeconds / $maxRequests) * 1_000_000);
|
|
|
|
$lastRequestAt = $this->cache->get($cacheKey);
|
|
|
|
if (is_numeric($lastRequestAt)) {
|
|
$elapsedMicroseconds = (int) ((microtime(true) - (float) $lastRequestAt) * 1_000_000);
|
|
|
|
if ($elapsedMicroseconds < $minIntervalMicroseconds) {
|
|
$sleepMicroseconds = $minIntervalMicroseconds - $elapsedMicroseconds;
|
|
|
|
if ($sleepMicroseconds > 0) {
|
|
usleep($sleepMicroseconds);
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->cache->put(
|
|
$cacheKey,
|
|
microtime(true),
|
|
now()->addSeconds((int) max(1, ceil($perSeconds * 2)))
|
|
);
|
|
}
|
|
|
|
protected function makeCacheKey(string $bucket, string $identity): string
|
|
{
|
|
return sprintf(
|
|
'laravel_bitunix_api:rate_limit:%s:%s',
|
|
$bucket,
|
|
sha1($identity)
|
|
);
|
|
}
|
|
}
|