Add CacheRateLimiter
This commit is contained in:
1 parent
a58ece7076
commit
bf9bcd4f7e
4 files changed
+80
-3
No files matched your search
@@ -0,0 +1,57 @@
|
||||
<?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)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user