-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPdoRateLimitStore.php
More file actions
124 lines (103 loc) · 3.8 KB
/
Copy pathPdoRateLimitStore.php
File metadata and controls
124 lines (103 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
declare(strict_types=1);
/**
* This file is part of the MultiFlexi package
*
* https://github.com/VitexSoftware/php-vitexsoftware-rbczpremiumapi
*
* (c) Vítězslav Dvořák <http://vitexsoftware.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace VitexSoftware\Raiffeisenbank\RateLimit;
class PdoRateLimitStore implements RateLimitStoreInterface
{
private \PDO $pdo;
/**
* Store the PDO connection and ensure the rate_limits table exists.
*
* Initializes the store by saving the provided PDO instance and creating the
* `rate_limits` table if it does not already exist.
*/
public function __construct(\PDO $pdo)
{
$this->pdo = $pdo;
$this->init();
}
/**
* Fetches the remaining token count and expiry timestamp for a client's rate-limit window.
*
* @param string $clientId Identifier of the client.
* @param string $window Identifier of the rate-limit window.
* @return array{remaining:int, timestamp:int}|null The row for the specified client and window with integer `remaining` and `timestamp`, or `null` if no record exists.
*/
public function get(string $clientId, string $window): ?array
{
$stmt = $this->pdo->prepare(<<<'EOD'
SELECT remaining, timestamp
FROM rate_limits
WHERE client_id = ? AND window = ?
EOD);
$stmt->execute([$clientId, $window]);
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
return $row ?: null;
}
/**
* Store or update the rate-limit record for a client and window.
*
* @param string $clientId Identifier of the client.
* @param string $window Identifier of the rate-limit window (e.g., "1m", "hourly").
* @param int $remaining Number of remaining allowed requests for the window.
* @param int $timestamp UNIX timestamp associated with the record (seconds since epoch).
*/
public function set(string $clientId, string $window, int $remaining, int $timestamp): void
{
$stmt = $this->pdo->prepare(<<<'EOD'
REPLACE INTO rate_limits (client_id, window, remaining, timestamp)
VALUES (?, ?, ?, ?)
EOD);
$stmt->execute([$clientId, $window, $remaining, $timestamp]);
}
/**
* Fetches all rate-limit entries for a client, indexed by window.
*
* @param string $clientId The client identifier.
* @return array<string, array{remaining:int,timestamp:int}> Associative array keyed by window name; each value contains `remaining` (int) and `timestamp` (int).
*/
public function allForClient(string $clientId): array
{
$stmt = $this->pdo->prepare(<<<'EOD'
SELECT window, remaining, timestamp
FROM rate_limits
WHERE client_id = ?
EOD);
$stmt->execute([$clientId]);
$results = [];
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
$results[$row['window']] = [
'remaining' => (int) $row['remaining'],
'timestamp' => (int) $row['timestamp'],
];
}
return $results;
}
/**
* Ensure the `rate_limits` table exists in the connected PDO database.
*
* Creates a table with columns: `client_id` (TEXT), `window` (TEXT), `remaining` (INTEGER),
* `timestamp` (INTEGER) and a composite primary key on (`client_id`, `window`).
*/
private function init(): void
{
$this->pdo->exec(<<<'EOD'
CREATE TABLE IF NOT EXISTS rate_limits (
client_id TEXT NOT NULL,
window TEXT NOT NULL,
remaining INTEGER NOT NULL,
timestamp INTEGER NOT NULL,
PRIMARY KEY (client_id, window)
)
EOD);
}
}