From 9d9bae3aa2723091d7ceaec52d6357975b608b42 Mon Sep 17 00:00:00 2001 From: Yassine Doghri Date: Tue, 13 Apr 2021 16:32:46 +0000 Subject: [PATCH 1/5] feat(cache): add deleteMatching method to remove multiple cache items at once using a glob pattern The implementation is only effective for file and redis/predis handlers. Because of certain limitations, memcached and wincache handlers do not implement the method. Both would require to go through the whole cache store (if it ever could) and match each keys against the glob pattern. That would inevitably result in performance issues. --- system/Cache/CacheInterface.php | 11 ++++++++ system/Cache/Handlers/DummyHandler.php | 14 ++++++++++ system/Cache/Handlers/FileHandler.php | 24 ++++++++++++++++ system/Cache/Handlers/MemcachedHandler.php | 14 ++++++++++ system/Cache/Handlers/PredisHandler.php | 25 +++++++++++++++++ system/Cache/Handlers/RedisHandler.php | 28 +++++++++++++++++++ system/Cache/Handlers/WincacheHandler.php | 16 +++++++++++ system/Test/Mock/MockCache.php | 22 +++++++++++++++ .../Cache/Handlers/DummyHandlerTest.php | 5 ++++ .../system/Cache/Handlers/FileHandlerTest.php | 22 +++++++++++++++ .../Cache/Handlers/MemcachedHandlerTest.php | 6 ++++ .../Cache/Handlers/PredisHandlerTest.php | 23 +++++++++++++++ .../Cache/Handlers/RedisHandlerTest.php | 23 +++++++++++++++ 13 files changed, 233 insertions(+) diff --git a/system/Cache/CacheInterface.php b/system/Cache/CacheInterface.php index a632b8de7687..3714faeb9296 100644 --- a/system/Cache/CacheInterface.php +++ b/system/Cache/CacheInterface.php @@ -58,6 +58,17 @@ public function delete(string $key); //-------------------------------------------------------------------- + /** + * Deletes items from the cache store matching a given pattern. + * + * @param string $pattern Cache items glob like pattern + * + * @return mixed + */ + public function deleteMatching(string $pattern); + + //-------------------------------------------------------------------- + /** * Performs atomic incrementation of a raw stored value. * diff --git a/system/Cache/Handlers/DummyHandler.php b/system/Cache/Handlers/DummyHandler.php index b888a98cec0e..8a721eb150ee 100644 --- a/system/Cache/Handlers/DummyHandler.php +++ b/system/Cache/Handlers/DummyHandler.php @@ -88,6 +88,20 @@ public function delete(string $key) //-------------------------------------------------------------------- + /** + * Deletes items from the cache store matching a given pattern. + * + * @param string $pattern Cache items glob like pattern + * + * @return boolean + */ + public function deleteMatching(string $pattern) + { + return true; + } + + //-------------------------------------------------------------------- + /** * Performs atomic incrementation of a raw stored value. * diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index a2cdbe8c135c..efea9645260a 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -160,6 +160,30 @@ public function delete(string $key) //-------------------------------------------------------------------- + /** + * Deletes items from the cache store matching a given pattern. + * + * @param string $pattern Cache items glob like pattern + * + * @return boolean + */ + public function deleteMatching(string $pattern) + { + $success = true; + + foreach (glob($this->path . $pattern) as $filename) + { + if (! is_file($filename) || ! unlink($filename)) + { + $success = false; + } + } + + return $success; + } + + //-------------------------------------------------------------------- + /** * Performs atomic incrementation of a raw stored value. * diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php index ea1a9e3ed1d0..3ef7c9fb662e 100644 --- a/system/Cache/Handlers/MemcachedHandler.php +++ b/system/Cache/Handlers/MemcachedHandler.php @@ -249,6 +249,20 @@ public function delete(string $key) //-------------------------------------------------------------------- + /** + * Deletes items from the cache store matching a given pattern. + * + * @param string $pattern Cache items glob like pattern + * + * @return boolean + */ + public function deleteMatching(string $pattern) + { + return false; + } + + //-------------------------------------------------------------------- + /** * Performs atomic incrementation of a raw stored value. * diff --git a/system/Cache/Handlers/PredisHandler.php b/system/Cache/Handlers/PredisHandler.php index 145d560f28c3..f5b1c224cc7a 100644 --- a/system/Cache/Handlers/PredisHandler.php +++ b/system/Cache/Handlers/PredisHandler.php @@ -15,6 +15,7 @@ use Config\Cache; use Exception; use Predis\Client; +use Predis\Collection\Iterator; /** * Predis cache handler @@ -184,6 +185,30 @@ public function delete(string $key) //-------------------------------------------------------------------- + /** + * Deletes items from the cache store matching a given pattern. + * + * @param string $pattern Cache items glob like pattern + * + * @return boolean + */ + public function deleteMatching(string $pattern) + { + $success = true; + + foreach (new Iterator\Keyspace($this->redis, $pattern) as $key) + { + if ($this->redis->del($key) !== 1) + { + $success = false; + } + } + + return $success; + } + + //-------------------------------------------------------------------- + /** * Performs atomic incrementation of a raw stored value. * diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php index a7fdcb9da2d5..e93c5d532c2c 100644 --- a/system/Cache/Handlers/RedisHandler.php +++ b/system/Cache/Handlers/RedisHandler.php @@ -223,6 +223,34 @@ public function delete(string $key) //-------------------------------------------------------------------- + /** + * Deletes items from the cache store matching a given pattern. + * + * @param string $pattern Cache items glob like pattern + * + * @return boolean + */ + public function deleteMatching(string $pattern) + { + $success = true; + $iterator = null; + + while ($keys = $this->redis->scan($iterator, $pattern)) + { + foreach ($keys as $key) + { + if ($this->redis->del($key) !== 1) + { + $success = false; + } + } + } + + return $success; + } + + //-------------------------------------------------------------------- + /** * Performs atomic incrementation of a raw stored value. * diff --git a/system/Cache/Handlers/WincacheHandler.php b/system/Cache/Handlers/WincacheHandler.php index 2ad1238e9592..3b49e3953118 100644 --- a/system/Cache/Handlers/WincacheHandler.php +++ b/system/Cache/Handlers/WincacheHandler.php @@ -113,6 +113,22 @@ public function delete(string $key) //-------------------------------------------------------------------- + /** + * Deletes items from the cache store matching a given pattern. + * + * @param string $pattern Cache items glob like pattern + * + * @return boolean + * + * @codeCoverageIgnore + */ + public function deleteMatching(string $pattern) + { + return false; + } + + //-------------------------------------------------------------------- + /** * Performs atomic incrementation of a raw stored value. * diff --git a/system/Test/Mock/MockCache.php b/system/Test/Mock/MockCache.php index 67356cf50f62..c2475f09a8ec 100644 --- a/system/Test/Mock/MockCache.php +++ b/system/Test/Mock/MockCache.php @@ -123,6 +123,28 @@ public function delete(string $key) //-------------------------------------------------------------------- + /** + * Deletes items from the cache store matching a given pattern. + * + * @param string $pattern Cache items pattern + * + * @return boolean + */ + public function deleteMatching(string $pattern) + { + foreach ($this->cache as $key => $value) + { + if (fnmatch($pattern, $key)) + { + unset($this->cache[$key]); + } + } + + return true; + } + + //-------------------------------------------------------------------- + /** * Performs atomic incrementation of a raw stored value. * diff --git a/tests/system/Cache/Handlers/DummyHandlerTest.php b/tests/system/Cache/Handlers/DummyHandlerTest.php index 72c89db5b395..4a200fa695b1 100644 --- a/tests/system/Cache/Handlers/DummyHandlerTest.php +++ b/tests/system/Cache/Handlers/DummyHandlerTest.php @@ -41,6 +41,11 @@ public function testDelete() $this->assertTrue($this->dummyHandler->delete('key')); } + public function testDeleteMatching() + { + $this->assertTrue($this->dummyHandler->deleteMatching('key*')); + } + public function testIncrement() { $this->assertTrue($this->dummyHandler->increment('key')); diff --git a/tests/system/Cache/Handlers/FileHandlerTest.php b/tests/system/Cache/Handlers/FileHandlerTest.php index 69c0460f87e2..b2b126634f8b 100644 --- a/tests/system/Cache/Handlers/FileHandlerTest.php +++ b/tests/system/Cache/Handlers/FileHandlerTest.php @@ -13,6 +13,7 @@ class FileHandlerTest extends CIUnitTestCase private static $key1 = 'key1'; private static $key2 = 'key2'; private static $key3 = 'key3'; + private static $key4 = 'another_key'; private static function getKeyArray() { @@ -20,6 +21,7 @@ private static function getKeyArray() self::$key1, self::$key2, self::$key3, + self::$key4, ]; } @@ -133,6 +135,26 @@ public function testDelete() $this->assertFalse($this->fileHandler->delete(self::$dummy)); } + public function testDeleteMatching() + { + $this->fileHandler->save(self::$key1, 'value'); + $this->fileHandler->save(self::$key2, 'value2'); + $this->fileHandler->save(self::$key3, 'value3'); + $this->fileHandler->save(self::$key4, 'value4'); + + $this->assertSame('value', $this->fileHandler->get(self::$key1)); + $this->assertSame('value2', $this->fileHandler->get(self::$key2)); + $this->assertSame('value3', $this->fileHandler->get(self::$key3)); + $this->assertSame('value4', $this->fileHandler->get(self::$key4)); + + $this->assertTrue($this->fileHandler->deleteMatching('key*')); + + $this->assertNull($this->fileHandler->get(self::$key1)); + $this->assertNull($this->fileHandler->get(self::$key2)); + $this->assertNull($this->fileHandler->get(self::$key3)); + $this->assertSame('value4', $this->fileHandler->get(self::$key4)); + } + public function testIncrement() { $this->fileHandler->save(self::$key1, 1); diff --git a/tests/system/Cache/Handlers/MemcachedHandlerTest.php b/tests/system/Cache/Handlers/MemcachedHandlerTest.php index 32abcbec9a4c..c099ff9c0cee 100644 --- a/tests/system/Cache/Handlers/MemcachedHandlerTest.php +++ b/tests/system/Cache/Handlers/MemcachedHandlerTest.php @@ -89,6 +89,12 @@ public function testDelete() $this->assertFalse($this->memcachedHandler->delete(self::$dummy)); } + public function testDeleteMatching() + { + // Not implemented for Memcached, should always return false + $this->assertFalse($this->memcachedHandler->deleteMatching('key*')); + } + public function testIncrement() { $this->memcachedHandler->save(self::$key1, 1); diff --git a/tests/system/Cache/Handlers/PredisHandlerTest.php b/tests/system/Cache/Handlers/PredisHandlerTest.php index 121d53569024..7261253eaba4 100644 --- a/tests/system/Cache/Handlers/PredisHandlerTest.php +++ b/tests/system/Cache/Handlers/PredisHandlerTest.php @@ -12,12 +12,15 @@ class PredisHandlerTest extends CIUnitTestCase private static $key1 = 'key1'; private static $key2 = 'key2'; private static $key3 = 'key3'; + private static $key4 = 'another_key'; + private static function getKeyArray() { return [ self::$key1, self::$key2, self::$key3, + self::$key4, ]; } @@ -97,6 +100,26 @@ public function testDelete() $this->assertFalse($this->PredisHandler->delete(self::$dummy)); } + public function testDeleteMatching() + { + $this->PredisHandler->save(self::$key1, 'value'); + $this->PredisHandler->save(self::$key2, 'value2'); + $this->PredisHandler->save(self::$key3, 'value3'); + $this->PredisHandler->save(self::$key4, 'value4'); + + $this->assertSame('value', $this->PredisHandler->get(self::$key1)); + $this->assertSame('value2', $this->PredisHandler->get(self::$key2)); + $this->assertSame('value3', $this->PredisHandler->get(self::$key3)); + $this->assertSame('value4', $this->PredisHandler->get(self::$key4)); + + $this->assertTrue($this->PredisHandler->deleteMatching('key*')); + + $this->assertNull($this->PredisHandler->get(self::$key1)); + $this->assertNull($this->PredisHandler->get(self::$key2)); + $this->assertNull($this->PredisHandler->get(self::$key3)); + $this->assertSame('value4', $this->PredisHandler->get(self::$key4)); + } + public function testClean() { $this->PredisHandler->save(self::$key1, 1); diff --git a/tests/system/Cache/Handlers/RedisHandlerTest.php b/tests/system/Cache/Handlers/RedisHandlerTest.php index ab390bd69869..50f8ed2a7b72 100644 --- a/tests/system/Cache/Handlers/RedisHandlerTest.php +++ b/tests/system/Cache/Handlers/RedisHandlerTest.php @@ -12,12 +12,15 @@ class RedisHandlerTest extends CIUnitTestCase private static $key1 = 'key1'; private static $key2 = 'key2'; private static $key3 = 'key3'; + private static $key4 = 'another_key'; + private static function getKeyArray() { return [ self::$key1, self::$key2, self::$key3, + self::$key4, ]; } @@ -97,6 +100,26 @@ public function testDelete() $this->assertFalse($this->redisHandler->delete(self::$dummy)); } + public function testDeleteMatching() + { + $this->redisHandler->save(self::$key1, 'value'); + $this->redisHandler->save(self::$key2, 'value2'); + $this->redisHandler->save(self::$key3, 'value3'); + $this->redisHandler->save(self::$key4, 'value4'); + + $this->assertSame('value', $this->redisHandler->get(self::$key1)); + $this->assertSame('value2', $this->redisHandler->get(self::$key2)); + $this->assertSame('value3', $this->redisHandler->get(self::$key3)); + $this->assertSame('value4', $this->redisHandler->get(self::$key4)); + + $this->assertTrue($this->redisHandler->deleteMatching('key*')); + + $this->assertNull($this->redisHandler->get(self::$key1)); + $this->assertNull($this->redisHandler->get(self::$key2)); + $this->assertNull($this->redisHandler->get(self::$key3)); + $this->assertSame('value4', $this->redisHandler->get(self::$key4)); + } + //FIXME: I don't like all Hash logic very much. It's wasting memory. //public function testIncrement() //{ From 82991df24131398e16a333a91c699933c7c15e8e Mon Sep 17 00:00:00 2001 From: Yassine Doghri Date: Tue, 13 Apr 2021 18:46:55 +0000 Subject: [PATCH 2/5] fix(rector): update code style --- system/Cache/Handlers/FileHandler.php | 2 +- system/Cache/Handlers/PredisHandler.php | 4 ++-- system/Test/Mock/MockCache.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index efea9645260a..164cece76b04 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -173,7 +173,7 @@ public function deleteMatching(string $pattern) foreach (glob($this->path . $pattern) as $filename) { - if (! is_file($filename) || ! unlink($filename)) + if (! is_file($filename) || ! @unlink($filename)) { $success = false; } diff --git a/system/Cache/Handlers/PredisHandler.php b/system/Cache/Handlers/PredisHandler.php index f5b1c224cc7a..327aed1db0e1 100644 --- a/system/Cache/Handlers/PredisHandler.php +++ b/system/Cache/Handlers/PredisHandler.php @@ -15,7 +15,7 @@ use Config\Cache; use Exception; use Predis\Client; -use Predis\Collection\Iterator; +use Predis\Collection\Iterator\Keyspace; /** * Predis cache handler @@ -196,7 +196,7 @@ public function deleteMatching(string $pattern) { $success = true; - foreach (new Iterator\Keyspace($this->redis, $pattern) as $key) + foreach (new Keyspace($this->redis, $pattern) as $key) { if ($this->redis->del($key) !== 1) { diff --git a/system/Test/Mock/MockCache.php b/system/Test/Mock/MockCache.php index c2475f09a8ec..7877303c1c1b 100644 --- a/system/Test/Mock/MockCache.php +++ b/system/Test/Mock/MockCache.php @@ -132,7 +132,7 @@ public function delete(string $key) */ public function deleteMatching(string $pattern) { - foreach ($this->cache as $key => $value) + foreach (array_keys($this->cache) as $key) { if (fnmatch($pattern, $key)) { From 72934cd139a95b6ee1ec458e613eb21e53f42e9d Mon Sep 17 00:00:00 2001 From: Yassine Doghri Date: Wed, 14 Apr 2021 10:18:25 +0000 Subject: [PATCH 3/5] fix: throw exception if deleteMatching used with memcached/wincache --- system/Cache/CacheInterface.php | 2 +- system/Cache/Handlers/DummyHandler.php | 2 +- system/Cache/Handlers/FileHandler.php | 2 +- system/Cache/Handlers/MemcachedHandler.php | 6 +++--- system/Cache/Handlers/PredisHandler.php | 2 +- system/Cache/Handlers/RedisHandler.php | 2 +- system/Cache/Handlers/WincacheHandler.php | 7 ++++--- system/Test/Mock/MockCache.php | 2 +- 8 files changed, 13 insertions(+), 12 deletions(-) diff --git a/system/Cache/CacheInterface.php b/system/Cache/CacheInterface.php index 3714faeb9296..68257eb2961a 100644 --- a/system/Cache/CacheInterface.php +++ b/system/Cache/CacheInterface.php @@ -61,7 +61,7 @@ public function delete(string $key); /** * Deletes items from the cache store matching a given pattern. * - * @param string $pattern Cache items glob like pattern + * @param string $pattern Cache items glob-style pattern * * @return mixed */ diff --git a/system/Cache/Handlers/DummyHandler.php b/system/Cache/Handlers/DummyHandler.php index 8a721eb150ee..5f6e50d5762a 100644 --- a/system/Cache/Handlers/DummyHandler.php +++ b/system/Cache/Handlers/DummyHandler.php @@ -91,7 +91,7 @@ public function delete(string $key) /** * Deletes items from the cache store matching a given pattern. * - * @param string $pattern Cache items glob like pattern + * @param string $pattern Cache items glob-style pattern * * @return boolean */ diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index 164cece76b04..d184d19f0dd4 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -163,7 +163,7 @@ public function delete(string $key) /** * Deletes items from the cache store matching a given pattern. * - * @param string $pattern Cache items glob like pattern + * @param string $pattern Cache items glob-style pattern * * @return boolean */ diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php index 3ef7c9fb662e..8758b01423cc 100644 --- a/system/Cache/Handlers/MemcachedHandler.php +++ b/system/Cache/Handlers/MemcachedHandler.php @@ -252,13 +252,13 @@ public function delete(string $key) /** * Deletes items from the cache store matching a given pattern. * - * @param string $pattern Cache items glob like pattern + * @param string $pattern Cache items glob-style pattern * - * @return boolean + * @throws Exception */ public function deleteMatching(string $pattern) { - return false; + throw new Exception('The deleteMatching method is not implemented for Memcached. You must select File, Redis or Predis handlers to use it.'); } //-------------------------------------------------------------------- diff --git a/system/Cache/Handlers/PredisHandler.php b/system/Cache/Handlers/PredisHandler.php index 327aed1db0e1..5b932733cc88 100644 --- a/system/Cache/Handlers/PredisHandler.php +++ b/system/Cache/Handlers/PredisHandler.php @@ -188,7 +188,7 @@ public function delete(string $key) /** * Deletes items from the cache store matching a given pattern. * - * @param string $pattern Cache items glob like pattern + * @param string $pattern Cache items glob-style pattern * * @return boolean */ diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php index e93c5d532c2c..d5fad5b86ce8 100644 --- a/system/Cache/Handlers/RedisHandler.php +++ b/system/Cache/Handlers/RedisHandler.php @@ -226,7 +226,7 @@ public function delete(string $key) /** * Deletes items from the cache store matching a given pattern. * - * @param string $pattern Cache items glob like pattern + * @param string $pattern Cache items glob-style pattern * * @return boolean */ diff --git a/system/Cache/Handlers/WincacheHandler.php b/system/Cache/Handlers/WincacheHandler.php index 3b49e3953118..f6ca9d8d5d40 100644 --- a/system/Cache/Handlers/WincacheHandler.php +++ b/system/Cache/Handlers/WincacheHandler.php @@ -12,6 +12,7 @@ namespace CodeIgniter\Cache\Handlers; use Config\Cache; +use Exception; /** * Cache handler for WinCache from Microsoft & IIS. @@ -116,15 +117,15 @@ public function delete(string $key) /** * Deletes items from the cache store matching a given pattern. * - * @param string $pattern Cache items glob like pattern + * @param string $pattern Cache items glob-style pattern * - * @return boolean + * @throws Exception * * @codeCoverageIgnore */ public function deleteMatching(string $pattern) { - return false; + throw new Exception('The deleteMatching method is not implemented for Wincache. You must select File, Redis or Predis handlers to use it.'); } //-------------------------------------------------------------------- diff --git a/system/Test/Mock/MockCache.php b/system/Test/Mock/MockCache.php index 7877303c1c1b..368b3b0f7ee9 100644 --- a/system/Test/Mock/MockCache.php +++ b/system/Test/Mock/MockCache.php @@ -126,7 +126,7 @@ public function delete(string $key) /** * Deletes items from the cache store matching a given pattern. * - * @param string $pattern Cache items pattern + * @param string $pattern Cache items glob-style pattern * * @return boolean */ From 3eccab5941d0ef59f4d93a54c06fabc1ff5e7775 Mon Sep 17 00:00:00 2001 From: Yassine Doghri Date: Wed, 14 Apr 2021 14:30:06 +0000 Subject: [PATCH 4/5] docs: add deleteMatching method to caching page --- user_guide_src/source/libraries/caching.rst | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/user_guide_src/source/libraries/caching.rst b/user_guide_src/source/libraries/caching.rst index 3f5b8109c30a..c3f7720d31bc 100644 --- a/user_guide_src/source/libraries/caching.rst +++ b/user_guide_src/source/libraries/caching.rst @@ -136,6 +136,27 @@ Class Reference $cache->delete('cache_item_id'); +.. php:method:: deleteMatching($pattern): bool + + :param string $pattern: glob-style pattern to match cached items keys + :returns: ``true`` on success, ``false`` if one of the deletes fails + :rtype: bool + + This method will delete multiple items from the cache store at once by + matching their keys against a glob pattern. + If one of the cache item deletion fails, the method will return FALSE. + + .. important:: This method is only implemented for File, Redis and Predis handlers. + Due to limitations, it couldn't be implemented for Memcached and Wincache handlers. + + Example:: + + $cache->deleteMatching('prefix_*'); // deletes all keys starting with "prefix_" + $cache->deleteMatching('*_suffix'); // deletes all keys ending with "_suffix" + + For more information on glob-style syntax, please see + `https://en.wikipedia.org/wiki/Glob_(programming) `_. + .. php:method:: increment($key[, $offset = 1]): mixed :param string $key: Cache ID From 3a42db199cb713ddd2e1f12cb58d9f755bb4433f Mon Sep 17 00:00:00 2001 From: Yassine Doghri Date: Mon, 19 Apr 2021 10:35:35 +0000 Subject: [PATCH 5/5] refactor: move deleteMatching out of CacheInterface to BaseHandler fix memcached tests by checking if it throws an exception --- system/Cache/CacheInterface.php | 11 ----------- system/Cache/Handlers/BaseHandler.php | 15 +++++++++++++++ .../Cache/Handlers/MemcachedHandlerTest.php | 7 +++++-- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/system/Cache/CacheInterface.php b/system/Cache/CacheInterface.php index 68257eb2961a..a632b8de7687 100644 --- a/system/Cache/CacheInterface.php +++ b/system/Cache/CacheInterface.php @@ -58,17 +58,6 @@ public function delete(string $key); //-------------------------------------------------------------------- - /** - * Deletes items from the cache store matching a given pattern. - * - * @param string $pattern Cache items glob-style pattern - * - * @return mixed - */ - public function deleteMatching(string $pattern); - - //-------------------------------------------------------------------- - /** * Performs atomic incrementation of a raw stored value. * diff --git a/system/Cache/Handlers/BaseHandler.php b/system/Cache/Handlers/BaseHandler.php index 10c2b3e82fe0..b2d17d369c2e 100644 --- a/system/Cache/Handlers/BaseHandler.php +++ b/system/Cache/Handlers/BaseHandler.php @@ -13,6 +13,7 @@ use Closure; use CodeIgniter\Cache\CacheInterface; +use Exception; /** * Base class for cache handling @@ -41,4 +42,18 @@ public function remember(string $key, int $ttl, Closure $callback) return $value; } + + //-------------------------------------------------------------------- + + /** + * Deletes items from the cache store matching a given pattern. + * + * @param string $pattern Cache items glob-style pattern + * + * @throws Exception + */ + public function deleteMatching(string $pattern) + { + throw new Exception('The deleteMatching method is not implemented.'); + } } diff --git a/tests/system/Cache/Handlers/MemcachedHandlerTest.php b/tests/system/Cache/Handlers/MemcachedHandlerTest.php index c099ff9c0cee..ff3ab1027942 100644 --- a/tests/system/Cache/Handlers/MemcachedHandlerTest.php +++ b/tests/system/Cache/Handlers/MemcachedHandlerTest.php @@ -5,6 +5,7 @@ use CodeIgniter\CLI\CLI; use CodeIgniter\Test\CIUnitTestCase; use Config\Cache; +use Exception; class MemcachedHandlerTest extends CIUnitTestCase { @@ -91,8 +92,10 @@ public function testDelete() public function testDeleteMatching() { - // Not implemented for Memcached, should always return false - $this->assertFalse($this->memcachedHandler->deleteMatching('key*')); + // Not implemented for Memcached, should throw an exception + $this->expectException(Exception::class); + + $this->memcachedHandler->deleteMatching('key*'); } public function testIncrement()