Skip to content

Commit

Permalink
Merge pull request #4567 from yassinedoghri/feat/cache-delete-matching
Browse files Browse the repository at this point in the history
feat(cache): add deleteMatching method to remove multiple cache items
  • Loading branch information
paulbalandan authored Apr 20, 2021
2 parents 8c5c2f4 + 3a42db1 commit ede6d96
Show file tree
Hide file tree
Showing 14 changed files with 262 additions and 0 deletions.
15 changes: 15 additions & 0 deletions system/Cache/Handlers/BaseHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Closure;
use CodeIgniter\Cache\CacheInterface;
use Exception;

/**
* Base class for cache handling
Expand Down Expand Up @@ -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.');
}
}
14 changes: 14 additions & 0 deletions system/Cache/Handlers/DummyHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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-style pattern
*
* @return boolean
*/
public function deleteMatching(string $pattern)
{
return true;
}

//--------------------------------------------------------------------

/**
* Performs atomic incrementation of a raw stored value.
*
Expand Down
24 changes: 24 additions & 0 deletions system/Cache/Handlers/FileHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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-style 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.
*
Expand Down
14 changes: 14 additions & 0 deletions system/Cache/Handlers/MemcachedHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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-style pattern
*
* @throws Exception
*/
public function deleteMatching(string $pattern)
{
throw new Exception('The deleteMatching method is not implemented for Memcached. You must select File, Redis or Predis handlers to use it.');
}

//--------------------------------------------------------------------

/**
* Performs atomic incrementation of a raw stored value.
*
Expand Down
25 changes: 25 additions & 0 deletions system/Cache/Handlers/PredisHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Config\Cache;
use Exception;
use Predis\Client;
use Predis\Collection\Iterator\Keyspace;

/**
* Predis cache handler
Expand Down Expand Up @@ -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-style pattern
*
* @return boolean
*/
public function deleteMatching(string $pattern)
{
$success = true;

foreach (new Keyspace($this->redis, $pattern) as $key)
{
if ($this->redis->del($key) !== 1)
{
$success = false;
}
}

return $success;
}

//--------------------------------------------------------------------

/**
* Performs atomic incrementation of a raw stored value.
*
Expand Down
28 changes: 28 additions & 0 deletions system/Cache/Handlers/RedisHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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-style 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.
*
Expand Down
17 changes: 17 additions & 0 deletions system/Cache/Handlers/WincacheHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace CodeIgniter\Cache\Handlers;

use Config\Cache;
use Exception;

/**
* Cache handler for WinCache from Microsoft & IIS.
Expand Down Expand Up @@ -113,6 +114,22 @@ public function delete(string $key)

//--------------------------------------------------------------------

/**
* Deletes items from the cache store matching a given pattern.
*
* @param string $pattern Cache items glob-style pattern
*
* @throws Exception
*
* @codeCoverageIgnore
*/
public function deleteMatching(string $pattern)
{
throw new Exception('The deleteMatching method is not implemented for Wincache. You must select File, Redis or Predis handlers to use it.');
}

//--------------------------------------------------------------------

/**
* Performs atomic incrementation of a raw stored value.
*
Expand Down
22 changes: 22 additions & 0 deletions system/Test/Mock/MockCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,28 @@ public function delete(string $key)

//--------------------------------------------------------------------

/**
* Deletes items from the cache store matching a given pattern.
*
* @param string $pattern Cache items glob-style pattern
*
* @return boolean
*/
public function deleteMatching(string $pattern)
{
foreach (array_keys($this->cache) as $key)
{
if (fnmatch($pattern, $key))
{
unset($this->cache[$key]);
}
}

return true;
}

//--------------------------------------------------------------------

/**
* Performs atomic incrementation of a raw stored value.
*
Expand Down
5 changes: 5 additions & 0 deletions tests/system/Cache/Handlers/DummyHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
Expand Down
22 changes: 22 additions & 0 deletions tests/system/Cache/Handlers/FileHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ 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()
{
return [
self::$key1,
self::$key2,
self::$key3,
self::$key4,
];
}

Expand Down Expand Up @@ -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);
Expand Down
9 changes: 9 additions & 0 deletions tests/system/Cache/Handlers/MemcachedHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use CodeIgniter\CLI\CLI;
use CodeIgniter\Test\CIUnitTestCase;
use Config\Cache;
use Exception;

class MemcachedHandlerTest extends CIUnitTestCase
{
Expand Down Expand Up @@ -89,6 +90,14 @@ public function testDelete()
$this->assertFalse($this->memcachedHandler->delete(self::$dummy));
}

public function testDeleteMatching()
{
// Not implemented for Memcached, should throw an exception
$this->expectException(Exception::class);

$this->memcachedHandler->deleteMatching('key*');
}

public function testIncrement()
{
$this->memcachedHandler->save(self::$key1, 1);
Expand Down
23 changes: 23 additions & 0 deletions tests/system/Cache/Handlers/PredisHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
];
}

Expand Down Expand Up @@ -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);
Expand Down
23 changes: 23 additions & 0 deletions tests/system/Cache/Handlers/RedisHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
];
}

Expand Down Expand Up @@ -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()
//{
Expand Down
Loading

0 comments on commit ede6d96

Please sign in to comment.