1
0
Fork 0

Merge pull request #5848 from nupplaphil/friendica-5847

friendica-5847 Console Cache List command doesn't work
This commit is contained in:
Hypolite Petovan 2018-10-07 17:47:51 -04:00 committed by GitHub
commit 3bccaccede
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 139 additions and 58 deletions

View file

@ -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
* *
* @return array|null Null if the driver doesn't support this feature * @param string $prefix Prefix of the keys (optional)
*
* @return array Empty 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');

View file

@ -17,8 +17,56 @@ 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 the keys of an array with a given prefix
* Returns the filtered keys as an new array
*
* @param array $array The array, which should get filtered
* @param string|null $prefix The prefix (if null, all keys will get returned)
*
* @return array The filtered array with just the keys
*/
protected function filterArrayKeysByPrefix($array, $prefix = null)
{
if (empty($prefix)) {
return array_keys($array);
} else {
$result = [];
foreach (array_keys($array) as $key) {
if (strpos($key, $prefix) === 0) {
array_push($result, $key);
}
}
return $result;
}
}
} }

View file

@ -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->filterArrayKeysByPrefix($this->cachedData, $prefix);
} }
/** /**

View file

@ -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);
$keys = [];
while ($key = DBA::fetch($stmt)) {
array_push($keys, $key['k']);
}
DBA::close($stmt);
return $keys;
} }
/** /**

View file

@ -14,9 +14,11 @@ interface ICacheDriver
/** /**
* Lists all cache keys * Lists all cache keys
* *
* @return array|null Null if it isn't supported by the cache driver * @param string prefix optional a prefix to search
*
* @return array Empty 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

View file

@ -43,23 +43,25 @@ class MemcacheCacheDriver extends AbstractCacheDriver implements IMemoryCacheDri
/** /**
* (@inheritdoc) * (@inheritdoc)
*/ */
public function getAllKeys() public function getAllKeys($prefix = null)
{ {
$list = []; $keys = [];
$allSlabs = $this->memcache->getExtendedStats('slabs'); $allSlabs = $this->memcache->getExtendedStats('slabs');
foreach ($allSlabs as $slabs) { foreach ($allSlabs as $slabs) {
foreach (array_keys($slabs) as $slabId) { foreach (array_keys($slabs) as $slabId) {
$cachedump = $this->memcache->getExtendedStats('cachedump', (int)$slabId); $cachedump = $this->memcache->getExtendedStats('cachedump', (int)$slabId);
foreach ($cachedump as $keys => $arrVal) { foreach ($cachedump as $key => $arrVal) {
if (!is_array($arrVal)) { if (!is_array($arrVal)) {
continue; continue;
} }
$list = array_merge($list, array_keys($arrVal)); $keys = array_merge($keys, array_keys($arrVal));
} }
} }
} }
return $list; $keys = $this->getOriginalKeys($keys);
return $this->filterArrayKeysByPrefix($keys, $prefix);
} }
/** /**

View file

@ -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;
/** /**
@ -56,9 +57,16 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr
/** /**
* (@inheritdoc) * (@inheritdoc)
*/ */
public function getAllKeys() public function getAllKeys($prefix = null)
{ {
return $this->memcached->getAllKeys(); $keys = $this->getOriginalKeys($this->memcached->getAllKeys());
if ($this->memcached->getResultCode() == Memcached::RES_SUCCESS) {
return $this->filterArrayKeysByPrefix($keys, $prefix);
} else {
logger('Memcached \'getAllKeys\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL);
return [];
}
} }
/** /**
@ -74,6 +82,8 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr
if ($this->memcached->getResultCode() === Memcached::RES_SUCCESS) { if ($this->memcached->getResultCode() === Memcached::RES_SUCCESS) {
$return = $value; $return = $value;
} else {
logger('Memcached \'get\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL);
} }
return $return; return $return;
@ -99,7 +109,6 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr
$value $value
); );
} }
} }
/** /**

View file

@ -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);
} }
/** /**

View file

@ -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:');
@ -115,11 +115,9 @@ HELP;
$count = 0; $count = 0;
foreach ($keys as $key) { foreach ($keys as $key) {
if (empty($prefix) || strpos($key, $prefix) === 0) {
$this->out($key); $this->out($key);
$count++; $count++;
} }
}
$this->out($count . ' keys found'); $this->out($count . ' keys found');
} }

View file

@ -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();

View file

@ -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);
}
} }

View file

@ -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');

View file

@ -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');

View file

@ -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');

View file

@ -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');