Skip to content

Commit

Permalink
feat: add task to remove cache entries in redis with specified prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
tinect committed Aug 28, 2024
1 parent 632436a commit 3b5c9a4
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 17 deletions.
1 change: 1 addition & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ parameters:
level: 8
paths:
- src
checkGenericClassInNonGenericObjectType: false
type_coverage:
return_type: 100
param_type: 98
Expand Down
36 changes: 19 additions & 17 deletions src/Components/CacheAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function getSize(): int
switch (true) {
case $this->adapter instanceof RedisAdapter:
case $this->adapter instanceof RedisTagAwareAdapter:
return $this->getRedis($this->adapter)->info()['used_memory'];
return $this->getRedis()->info()['used_memory'];
case $this->adapter instanceof FilesystemAdapter:
return CacheHelper::getSize($this->getPathFromFilesystemAdapter($this->adapter));
case $this->adapter instanceof ArrayAdapter:
Expand All @@ -57,7 +57,7 @@ public function getFreeSize(): ?int
switch (true) {
case $this->adapter instanceof RedisAdapter:
case $this->adapter instanceof RedisTagAwareAdapter:
$info = $this->getRedis($this->adapter)->info();
$info = $this->getRedis()->info();
if ($info['maxmemory'] === 0) {
return -1;
}
Expand All @@ -84,7 +84,7 @@ public function clear(): void
case $this->adapter instanceof RedisAdapter:
case $this->adapter instanceof RedisTagAwareAdapter:
try {
$this->getRedis($this->adapter)->flushDB();
$this->getRedis()->flushDB();
} catch (\Exception) {
$this->adapter->clear();
}
Expand All @@ -100,8 +100,8 @@ public function clear(): void
public function getType(): string
{
return match (true) {
$this->adapter instanceof RedisAdapter, => self::TYPE_REDIS . ' ' . $this->getRedis($this->adapter)->info()['redis_version'],
$this->adapter instanceof RedisTagAwareAdapter => self::TYPE_REDIS_TAG_AWARE . ' ' . $this->getRedis($this->adapter)->info()['redis_version'],
$this->adapter instanceof RedisAdapter, => self::TYPE_REDIS . ' ' . $this->getRedis()->info()['redis_version'],
$this->adapter instanceof RedisTagAwareAdapter => self::TYPE_REDIS_TAG_AWARE . ' ' . $this->getRedis()->info()['redis_version'],
$this->adapter instanceof FilesystemAdapter => self::TYPE_FILESYSTEM,
$this->adapter instanceof ArrayAdapter => self::TYPE_ARRAY,
$this->adapter instanceof PhpFilesAdapter => self::TYPE_PHP_FILES,
Expand All @@ -110,6 +110,20 @@ public function getType(): string
};
}

public function getRedis(): \Redis
{
$adapter = $this->adapter;

if ($adapter instanceof RedisTagAwareAdapter) {
$redisProxyGetter = \Closure::bind(fn() => $adapter->redis, $adapter, RedisTagAwareAdapter::class);
} else {
// @phpstan-ignore-next-line
$redisProxyGetter = \Closure::bind(fn() => $adapter->redis, $adapter, RedisAdapter::class);
}

return $redisProxyGetter();
}

private function getCacheAdapter(AdapterInterface $adapter): AdapterInterface
{
if ($adapter instanceof CacheDecorator) {
Expand All @@ -129,18 +143,6 @@ private function getCacheAdapter(AdapterInterface $adapter): AdapterInterface
return $adapter;
}

private function getRedis(AdapterInterface $adapter): \Redis
{
if ($adapter instanceof RedisTagAwareAdapter) {
$redisProxyGetter = \Closure::bind(fn() => $adapter->redis, $adapter, RedisTagAwareAdapter::class);
} else {
// @phpstan-ignore-next-line
$redisProxyGetter = \Closure::bind(fn() => $adapter->redis, $adapter, RedisAdapter::class);
}

return $redisProxyGetter();
}

private function getPathFromFilesystemAdapter(FilesystemAdapter $adapter): string
{
$getter = \Closure::bind(fn() => $adapter->directory, $adapter, $adapter::class);
Expand Down
22 changes: 22 additions & 0 deletions src/Task/RedisPrefixCleanupTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Frosh\Tools\Task;

use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTask;

class RedisPrefixCleanupTask extends ScheduledTask
{
final public const NAME = 'frosh.tools.redis_prefix_cleanup';

public static function getTaskName(): string
{
return self::NAME;
}

public static function getDefaultInterval(): int
{
return 86400;
}
}
71 changes: 71 additions & 0 deletions src/Task/RedisPrefixCleanupTaskHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace Frosh\Tools\Task;

use Frosh\Tools\Components\CacheRegistry;
use Psr\Log\LoggerInterface;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskHandler;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

#[AsMessageHandler(handles: RedisPrefixCleanupTask::class)]
class RedisPrefixCleanupTaskHandler extends ScheduledTaskHandler
{
public function __construct(
EntityRepository $scheduledTaskRepository,
LoggerInterface $logger,
private readonly CacheRegistry $cacheRegistry,
#[Autowire('%shopware.cache.redis_prefix%')]
private readonly string $redisPrefix,
) {
parent::__construct($scheduledTaskRepository, $logger);
}

public function run(): void
{
if ($this->redisPrefix === '') {
return;
}

try {
$redis = $this->cacheRegistry->get('cache.http')->getRedis();
} catch (\Throwable) {
return;
}

$cursor = null;
$count = 50;
$deleteKeys = [];

do {
$keys = $redis->scan($cursor, '*', $count);

if (!\is_array($keys)) {
return;
}

foreach ($keys as $key) {
if (\str_starts_with($key, $this->redisPrefix)) {
continue;
}

/**
* there could be shared database with session, cart or others,
* so we need to make sure that we only delete keys with no ttl
*/
if ($redis->ttl($key) !== -1) {
continue;
}

$deleteKeys[] = $key;
}
} while ($cursor !== 0);

foreach (\array_chunk($deleteKeys, $count) as $chunk) {
$redis->del($chunk);
}
}
}

0 comments on commit 3b5c9a4

Please sign in to comment.