Skip to content

Commit

Permalink
chore: optimise abuse
Browse files Browse the repository at this point in the history
  • Loading branch information
loks0n committed Dec 27, 2024
1 parent 54a5835 commit d985da2
Showing 1 changed file with 26 additions and 47 deletions.
73 changes: 26 additions & 47 deletions src/Abuse/Adapters/TimeLimit/Redis.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ class Redis extends TimeLimit
* @var \Redis
*/
protected \Redis $redis;

/**
* @var int
*/
protected int $ttl;

public function __construct(string $key, int $limit, int $seconds, \Redis $redis)
{
$this->redis = $redis;
$this->key = $key;
$this->ttl = $seconds;
$now = \time();
$this->timestamp = (int)($now - ($now % $seconds));
$this->limit = $limit;
Expand Down Expand Up @@ -62,16 +68,13 @@ protected function hit(string $key, int $timestamp): void
return;
}

/** @var string $count */
$count = $this->redis->get(self::NAMESPACE . '__'. $key .'__'. $timestamp);
if (!$count) {
$this->count = 0;
} else {
$this->count = intval($count);
}

$this->redis->incr(self::NAMESPACE . '__'. $key .'__'. $timestamp);
$this->count++;
$key = self::NAMESPACE . '__' . $key . '__' . $timestamp;
$this->redis->multi()
->incr($key)
->expire($key, $this->ttl)
->exec();

$this->count = ($this->count ?? 0) + 1;
}

/**
Expand All @@ -85,18 +88,19 @@ protected function hit(string $key, int $timestamp): void
*/
public function getLogs(?int $offset = null, ?int $limit = 25): array
{
// TODO limit potential is SCAN but needs cursor no offset
$cursor = null;
$keys = $this->redis->scan($cursor, self::NAMESPACE . '__*', $limit);
if (!$keys) {
return [];
}
$cursor = 0;
$matches = [];
$pattern = self::NAMESPACE . '__*';

do {
[$cursor, $keys] = $this->redis->scan($cursor, $pattern, $limit);
if (!empty($keys)) {
$values = $this->redis->mget($keys);
$matches = array_merge($matches, array_combine($keys, $values));
}
} while ($cursor > 0 && (!$limit || count($matches) < $limit));

$logs = [];
foreach ($keys as $key) {
$logs[$key] = $this->redis->get($key);
}
return $logs;
return $matches;
}

/**
Expand All @@ -107,32 +111,7 @@ public function getLogs(?int $offset = null, ?int $limit = 25): array
*/
public function cleanup(int $timestamp): bool
{
$iterator = null;
while ($iterator !== 0) {
$keys = $this->redis->scan($iterator, self::NAMESPACE . '__*__*', 1000);
$keys = $this->filterKeys($keys ? $keys : [], $timestamp);
$this->redis->del($keys);
}
// No need for manual cleanup - Redis TTL handles this automatically
return true;
}

/**
* Filter keys
*
* @param array<string> $keys
* @param integer $timestamp
* @return array<string>
*/
protected function filterKeys(array $keys, int $timestamp): array
{
$filteredKeys = [];
foreach ($keys as $key) {
$parts = explode('__', $key);
$keyTimestamp = (int)end($parts); // Assuming the last part is always the timestamp
if ($keyTimestamp < $timestamp) {
$filteredKeys[] = $key;
}
}
return $filteredKeys;
}
}

0 comments on commit d985da2

Please sign in to comment.