friendica-5847 Console Cache List command doesn't work
- Added $prefix to all CacheDriver - Moved hostname magic to CacheDriver - Added test for getAllKeys()
This commit is contained in:
parent
1551570b7f
commit
3f0f3b6ae6
15 changed files with 131 additions and 48 deletions
|
@ -51,20 +51,15 @@ class Cache extends \Friendica\BaseObject
|
||||||
/**
|
/**
|
||||||
* @brief Returns all the cache keys sorted alphabetically
|
* @brief Returns all the cache keys sorted alphabetically
|
||||||
*
|
*
|
||||||
|
* @param string $prefix Prefix of the keys (optional)
|
||||||
|
*
|
||||||
* @return array|null Null if the driver doesn't support this feature
|
* @return array|null Null if the driver doesn't support this feature
|
||||||
*/
|
*/
|
||||||
public static function getAllKeys()
|
public static function getAllKeys($prefix = null)
|
||||||
{
|
{
|
||||||
$time = microtime(true);
|
$time = microtime(true);
|
||||||
|
|
||||||
$return = self::getDriver()->getAllKeys();
|
$return = self::getDriver()->getAllKeys($prefix);
|
||||||
|
|
||||||
// Keys are prefixed with the node hostname, let's remove it
|
|
||||||
array_walk($return, function (&$value) {
|
|
||||||
$value = preg_replace('/^' . self::getApp()->get_hostname() . ':/', '', $value);
|
|
||||||
});
|
|
||||||
|
|
||||||
sort($return);
|
|
||||||
|
|
||||||
self::getApp()->save_timestamp($time, 'cache');
|
self::getApp()->save_timestamp($time, 'cache');
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,55 @@ abstract class AbstractCacheDriver extends BaseObject
|
||||||
* @param string $key The original key
|
* @param string $key The original key
|
||||||
* @return string The cache key used for the cache
|
* @return string The cache key used for the cache
|
||||||
*/
|
*/
|
||||||
protected function getCacheKey($key) {
|
protected function getCacheKey($key)
|
||||||
|
{
|
||||||
// We fetch with the hostname as key to avoid problems with other applications
|
// We fetch with the hostname as key to avoid problems with other applications
|
||||||
return self::getApp()->get_hostname() . ":" . $key;
|
return self::getApp()->get_hostname() . ":" . $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $keys A list of cached keys
|
||||||
|
* @return array A list of original keys
|
||||||
|
*/
|
||||||
|
protected function getOriginalKeys($keys)
|
||||||
|
{
|
||||||
|
if (empty($keys)) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
// Keys are prefixed with the node hostname, let's remove it
|
||||||
|
array_walk($keys, function (&$value) {
|
||||||
|
$value = preg_replace('/^' . self::getApp()->get_hostname() . ':/', '', $value);
|
||||||
|
});
|
||||||
|
|
||||||
|
sort($keys);
|
||||||
|
|
||||||
|
return $keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters a list for a given prefix
|
||||||
|
*
|
||||||
|
* @param array $list the list
|
||||||
|
* @param string|null $prefix the prefix
|
||||||
|
*
|
||||||
|
* @return array the filtered list
|
||||||
|
*/
|
||||||
|
protected function filterPrefix($list, $prefix = null)
|
||||||
|
{
|
||||||
|
if (empty($prefix)) {
|
||||||
|
return array_keys($list);
|
||||||
|
} else {
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
foreach (array_keys($list) as $key) {
|
||||||
|
if (strpos($key, $prefix) === 0) {
|
||||||
|
array_push($result, $key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,9 @@ class ArrayCache extends AbstractCacheDriver implements IMemoryCacheDriver
|
||||||
/**
|
/**
|
||||||
* (@inheritdoc)
|
* (@inheritdoc)
|
||||||
*/
|
*/
|
||||||
public function getAllKeys()
|
public function getAllKeys($prefix = null)
|
||||||
{
|
{
|
||||||
return array_keys($this->cachedData);
|
return $this->filterPrefix($this->cachedData, $prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,11 +16,23 @@ class DatabaseCacheDriver extends AbstractCacheDriver implements ICacheDriver
|
||||||
/**
|
/**
|
||||||
* (@inheritdoc)
|
* (@inheritdoc)
|
||||||
*/
|
*/
|
||||||
public function getAllKeys()
|
public function getAllKeys($prefix = null)
|
||||||
{
|
{
|
||||||
$stmt = DBA::select('cache', ['k'], ['`expires` >= ?', DateTimeFormat::utcNow()]);
|
if (empty($prefix)) {
|
||||||
|
$where = ['`expires` >= ?', DateTimeFormat::utcNow()];
|
||||||
|
} else {
|
||||||
|
$where = ['`expires` >= ? AND k LIKE CONCAT(?, \'%\')', DateTimeFormat::utcNow(), $prefix];
|
||||||
|
}
|
||||||
|
|
||||||
return DBA::toArray($stmt);
|
$stmt = DBA::select('cache', ['k'], $where);
|
||||||
|
|
||||||
|
$list = [];
|
||||||
|
while ($key = DBA::fetch($stmt)) {
|
||||||
|
array_push($list, $key['k']);
|
||||||
|
}
|
||||||
|
DBA::close($stmt);
|
||||||
|
|
||||||
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,9 +14,11 @@ interface ICacheDriver
|
||||||
/**
|
/**
|
||||||
* Lists all cache keys
|
* Lists all cache keys
|
||||||
*
|
*
|
||||||
|
* @param string prefix optional a prefix to search
|
||||||
|
*
|
||||||
* @return array|null Null if it isn't supported by the cache driver
|
* @return array|null Null if it isn't supported by the cache driver
|
||||||
*/
|
*/
|
||||||
public function getAllKeys();
|
public function getAllKeys($prefix = null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches cached data according to the key
|
* Fetches cached data according to the key
|
||||||
|
|
|
@ -43,7 +43,7 @@ class MemcacheCacheDriver extends AbstractCacheDriver implements IMemoryCacheDri
|
||||||
/**
|
/**
|
||||||
* (@inheritdoc)
|
* (@inheritdoc)
|
||||||
*/
|
*/
|
||||||
public function getAllKeys()
|
public function getAllKeys($prefix = null)
|
||||||
{
|
{
|
||||||
$list = [];
|
$list = [];
|
||||||
$allSlabs = $this->memcache->getExtendedStats('slabs');
|
$allSlabs = $this->memcache->getExtendedStats('slabs');
|
||||||
|
@ -59,7 +59,9 @@ class MemcacheCacheDriver extends AbstractCacheDriver implements IMemoryCacheDri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $list;
|
$list = $this->getOriginalKeys($list);
|
||||||
|
|
||||||
|
return $this->filterPrefix($list, $prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace Friendica\Core\Cache;
|
||||||
use Friendica\Core\Cache;
|
use Friendica\Core\Cache;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||||
use Memcached;
|
use Memcached;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +41,9 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr
|
||||||
|
|
||||||
$this->memcached = new Memcached();
|
$this->memcached = new Memcached();
|
||||||
|
|
||||||
|
|
||||||
|
$this->memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, false);
|
||||||
|
|
||||||
array_walk($memcached_hosts, function (&$value) {
|
array_walk($memcached_hosts, function (&$value) {
|
||||||
if (is_string($value)) {
|
if (is_string($value)) {
|
||||||
$value = array_map('trim', explode(',', $value));
|
$value = array_map('trim', explode(',', $value));
|
||||||
|
@ -56,9 +60,15 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr
|
||||||
/**
|
/**
|
||||||
* (@inheritdoc)
|
* (@inheritdoc)
|
||||||
*/
|
*/
|
||||||
public function getAllKeys()
|
public function getAllKeys($prefix = null)
|
||||||
{
|
{
|
||||||
return $this->memcached->getAllKeys();
|
// Doesn't work because of https://github.com/php-memcached-dev/php-memcached/issues/367
|
||||||
|
// returns everytime an empty array
|
||||||
|
throw new InternalServerErrorException('getAllKeys for Memcached not supported yet');
|
||||||
|
|
||||||
|
$list = $this->getOriginalKeys($this->memcached->getAllKeys());
|
||||||
|
|
||||||
|
return $this->filterPrefix($list, $prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -41,9 +41,17 @@ class RedisCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver
|
||||||
/**
|
/**
|
||||||
* (@inheritdoc)
|
* (@inheritdoc)
|
||||||
*/
|
*/
|
||||||
public function getAllKeys()
|
public function getAllKeys($prefix = null)
|
||||||
{
|
{
|
||||||
return null;
|
if (empty($prefix)) {
|
||||||
|
$search = '*';
|
||||||
|
} else {
|
||||||
|
$search = $prefix . '*';
|
||||||
|
}
|
||||||
|
|
||||||
|
$list = $this->redis->keys($this->getCacheKey($search));
|
||||||
|
|
||||||
|
return $this->getOriginalKeys($list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -105,7 +105,7 @@ HELP;
|
||||||
private function executeList()
|
private function executeList()
|
||||||
{
|
{
|
||||||
$prefix = $this->getArgument(1);
|
$prefix = $this->getArgument(1);
|
||||||
$keys = Core\Cache::getAllKeys();
|
$keys = Core\Cache::getAllKeys($prefix);
|
||||||
|
|
||||||
if (empty($prefix)) {
|
if (empty($prefix)) {
|
||||||
$this->out('Listing all cache keys:');
|
$this->out('Listing all cache keys:');
|
||||||
|
|
|
@ -7,11 +7,6 @@ use Friendica\Core\Cache\ArrayCache;
|
||||||
|
|
||||||
class ArrayCacheDriverTest extends MemoryCacheTest
|
class ArrayCacheDriverTest extends MemoryCacheTest
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var \Friendica\Core\Cache\IMemoryCacheDriver
|
|
||||||
*/
|
|
||||||
private $cache;
|
|
||||||
|
|
||||||
protected function getInstance()
|
protected function getInstance()
|
||||||
{
|
{
|
||||||
$this->cache = new ArrayCache();
|
$this->cache = new ArrayCache();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Friendica\Test\src\Core\Cache;
|
namespace Friendica\Test\src\Core\Cache;
|
||||||
|
|
||||||
|
use Friendica\Core\Cache\MemcachedCacheDriver;
|
||||||
use Friendica\Core\Config;
|
use Friendica\Core\Config;
|
||||||
use Friendica\Test\DatabaseTest;
|
use Friendica\Test\DatabaseTest;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
|
@ -13,6 +14,12 @@ abstract class CacheTest extends DatabaseTest
|
||||||
*/
|
*/
|
||||||
protected $instance;
|
protected $instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Friendica\Core\Cache\IMemoryCacheDriver
|
||||||
|
*/
|
||||||
|
protected $cache;
|
||||||
|
|
||||||
|
|
||||||
abstract protected function getInstance();
|
abstract protected function getInstance();
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
|
@ -29,6 +36,8 @@ abstract class CacheTest extends DatabaseTest
|
||||||
Config::set('system', 'throttle_limit_week', 100);
|
Config::set('system', 'throttle_limit_week', 100);
|
||||||
Config::set('system', 'throttle_limit_month', 100);
|
Config::set('system', 'throttle_limit_month', 100);
|
||||||
Config::set('system', 'theme', 'system_theme');
|
Config::set('system', 'theme', 'system_theme');
|
||||||
|
|
||||||
|
$this->instance->clear(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,4 +186,27 @@ abstract class CacheTest extends DatabaseTest
|
||||||
$received = $this->instance->get('objVal');
|
$received = $this->instance->get('objVal');
|
||||||
$this->assertEquals($value, $received, 'Value type changed from ' . gettype($value) . ' to ' . gettype($received));
|
$this->assertEquals($value, $received, 'Value type changed from ' . gettype($value) . ' to ' . gettype($received));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @small
|
||||||
|
*/
|
||||||
|
public function testGetAllKeys() {
|
||||||
|
if ($this->cache instanceof MemcachedCacheDriver) {
|
||||||
|
$this->markTestSkipped('Memcached doesn\'t support getAllKeys anymore');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertTrue($this->instance->set('value1', 'test'));
|
||||||
|
$this->assertTrue($this->instance->set('value2', 'test'));
|
||||||
|
$this->assertTrue($this->instance->set('test_value3', 'test'));
|
||||||
|
|
||||||
|
$list = $this->instance->getAllKeys();
|
||||||
|
|
||||||
|
$this->assertContains('value1', $list);
|
||||||
|
$this->assertContains('value2', $list);
|
||||||
|
$this->assertContains('test_value3', $list);
|
||||||
|
|
||||||
|
$list = $this->instance->getAllKeys('test');
|
||||||
|
|
||||||
|
$this->assertContains('test_value3', $list);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,6 @@ use Friendica\Core\Cache\CacheDriverFactory;
|
||||||
|
|
||||||
class DatabaseCacheDriverTest extends CacheTest
|
class DatabaseCacheDriverTest extends CacheTest
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var \Friendica\Core\Cache\IMemoryCacheDriver
|
|
||||||
*/
|
|
||||||
private $cache;
|
|
||||||
|
|
||||||
protected function getInstance()
|
protected function getInstance()
|
||||||
{
|
{
|
||||||
$this->cache = CacheDriverFactory::create('database');
|
$this->cache = CacheDriverFactory::create('database');
|
||||||
|
|
|
@ -11,11 +11,6 @@ use Friendica\Core\Cache\CacheDriverFactory;
|
||||||
*/
|
*/
|
||||||
class MemcacheCacheDriverTest extends MemoryCacheTest
|
class MemcacheCacheDriverTest extends MemoryCacheTest
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var \Friendica\Core\Cache\IMemoryCacheDriver
|
|
||||||
*/
|
|
||||||
private $cache;
|
|
||||||
|
|
||||||
protected function getInstance()
|
protected function getInstance()
|
||||||
{
|
{
|
||||||
$this->cache = CacheDriverFactory::create('memcache');
|
$this->cache = CacheDriverFactory::create('memcache');
|
||||||
|
|
|
@ -11,11 +11,6 @@ use Friendica\Core\Cache\CacheDriverFactory;
|
||||||
*/
|
*/
|
||||||
class MemcachedCacheDriverTest extends MemoryCacheTest
|
class MemcachedCacheDriverTest extends MemoryCacheTest
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var \Friendica\Core\Cache\IMemoryCacheDriver
|
|
||||||
*/
|
|
||||||
private $cache;
|
|
||||||
|
|
||||||
protected function getInstance()
|
protected function getInstance()
|
||||||
{
|
{
|
||||||
$this->cache = CacheDriverFactory::create('memcached');
|
$this->cache = CacheDriverFactory::create('memcached');
|
||||||
|
|
|
@ -11,11 +11,6 @@ use Friendica\Core\Cache\CacheDriverFactory;
|
||||||
*/
|
*/
|
||||||
class RedisCacheDriverTest extends MemoryCacheTest
|
class RedisCacheDriverTest extends MemoryCacheTest
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var \Friendica\Core\Cache\IMemoryCacheDriver
|
|
||||||
*/
|
|
||||||
private $cache;
|
|
||||||
|
|
||||||
protected function getInstance()
|
protected function getInstance()
|
||||||
{
|
{
|
||||||
$this->cache = CacheDriverFactory::create('redis');
|
$this->cache = CacheDriverFactory::create('redis');
|
||||||
|
|
Loading…
Reference in a new issue