Skip to content

Commit 35eba68

Browse files
authored
Merge pull request #30 from tareq-halaby/tareq-halaby-patch-5
Add RateLimiter class for query rate limiting
2 parents 314e004 + 344e70d commit 35eba68

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

src/RateLimiter.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SqlPowertools;
6+
7+
/**
8+
* RateLimiter - Query Rate Limiting Utility
9+
*
10+
* Prevents abuse by limiting the number of queries that can
11+
* be executed within a configurable time window.
12+
*
13+
* @package SqlPowertools
14+
* @version 1.2.0
15+
*/
16+
class RateLimiter
17+
{
18+
private array $buckets = [];
19+
20+
public function __construct(
21+
private readonly int $maxAttempts = 100,
22+
private readonly int $windowSeconds = 60
23+
) {}
24+
25+
/**
26+
* Check whether a key is allowed to proceed.
27+
*/
28+
public function attempt(string $key): bool
29+
{
30+
$this->cleanup($key);
31+
$count = count($this->buckets[$key] ?? []);
32+
33+
if ($count >= $this->maxAttempts) {
34+
return false;
35+
}
36+
37+
$this->buckets[$key][] = time();
38+
return true;
39+
}
40+
41+
/**
42+
* Get remaining attempts for a key.
43+
*/
44+
public function remaining(string $key): int
45+
{
46+
$this->cleanup($key);
47+
return max(0, $this->maxAttempts - count($this->buckets[$key] ?? []));
48+
}
49+
50+
/**
51+
* Reset attempts for a key.
52+
*/
53+
public function reset(string $key): void
54+
{
55+
unset($this->buckets[$key]);
56+
}
57+
58+
private function cleanup(string $key): void
59+
{
60+
$cutoff = time() - $this->windowSeconds;
61+
$this->buckets[$key] = array_filter(
62+
$this->buckets[$key] ?? [],
63+
fn(int $ts) => $ts > $cutoff
64+
);
65+
}
66+
}

0 commit comments

Comments
 (0)