From 932eafd9cf28ff234c19fd2e3fb79c096b898bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederic=20G=2E=20=C3=98stby?= Date: Mon, 4 Nov 2024 20:50:30 +0100 Subject: [PATCH] Don't use flushdb when clearing the cache Some systems will have FLUSHDB disabled and this also makes it easier to share a database between applications without flushing all cache if cache key prefixes are used. --- CHANGELOG.md | 1 + src/mako/cache/stores/Redis.php | 11 ++++++++++- tests/unit/cache/stores/RedisTest.php | 22 +++++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35a4c6c83..d5b0ffc0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1752,6 +1752,7 @@ The major version bump is due to dropped support for PHP `7.0` and `7.1` and a s * Removed support for "piped" validation rules. * New syntax for passing parameters to middleware. * New syntax for passing parameters to validation rules. +* The Redis cache `clear` implementation will no longer flush the entire database but instead just deleted the cached keys. #### Bugfixes diff --git a/src/mako/cache/stores/Redis.php b/src/mako/cache/stores/Redis.php index 579ef3be9..14bd82918 100644 --- a/src/mako/cache/stores/Redis.php +++ b/src/mako/cache/stores/Redis.php @@ -9,6 +9,7 @@ use mako\redis\Redis as RedisClient; +use function array_chunk; use function is_numeric; use function serialize; use function unserialize; @@ -112,6 +113,14 @@ public function remove(string $key): bool */ public function clear(): bool { - return (bool) $this->redis->flushdb(); + $keys = $this->redis->keys($this->getPrefixedKey('*')); + + if (!empty($keys)) { + foreach (array_chunk($keys, 100) as $chunk) { + $this->redis->del(...$chunk); + } + } + + return true; } } diff --git a/tests/unit/cache/stores/RedisTest.php b/tests/unit/cache/stores/RedisTest.php index 110a07f48..7a2154abf 100644 --- a/tests/unit/cache/stores/RedisTest.php +++ b/tests/unit/cache/stores/RedisTest.php @@ -298,10 +298,30 @@ public function testClear(): void { $client = $this->getRedisClient(); - $client->shouldReceive('flushdb')->once(); + $client->shouldReceive('keys')->once()->with('*')->andReturn(['foo', 'bar']); + + $client->shouldReceive('del')->once()->with('foo', 'bar')->andReturn(2); $redis = new Redis($client); $redis->clear(); } + + /** + * + */ + public function testClearWithPrefix(): void + { + $client = $this->getRedisClient(); + + $client->shouldReceive('keys')->once()->with('prefix.*')->andReturn(['prefix.foo', 'prefix.bar']); + + $client->shouldReceive('del')->once()->with('prefix.foo', 'prefix.bar')->andReturn(2); + + $redis = new Redis($client); + + $redis->setPrefix('prefix'); + + $redis->clear(); + } }