mirror of
https://github.com/friendica/friendica
synced 2024-11-09 16:22:56 +00:00
Adding possibility to use a different cache-backend for locking and caching
- Renaming *LockDriver to *Lock since it isn't a "driver" anymore
This commit is contained in:
parent
86bf2ee45a
commit
34e4968c06
19 changed files with 149 additions and 64 deletions
|
@ -5,8 +5,6 @@ namespace Friendica\Console;
|
|||
use Asika\SimpleConsole\CommandArgsException;
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Cache\ICache;
|
||||
use Friendica\Core\Config\Configuration;
|
||||
use Friendica\Factory\CacheDriverFactory;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
|
@ -71,13 +69,12 @@ HELP;
|
|||
return $help;
|
||||
}
|
||||
|
||||
public function __construct(App\Mode $appMode, Configuration $config, ICache $cache, array $argv = null)
|
||||
public function __construct(App\Mode $appMode, ICache $cache, array $argv = null)
|
||||
{
|
||||
parent::__construct($argv);
|
||||
|
||||
$this->appMode = $appMode;
|
||||
$this->cache = $cache;
|
||||
$this->cacheDriverName = $config->get('system', 'cache_driver', CacheDriverFactory::DEFAULT_DRIVER);
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
|
@ -94,7 +91,7 @@ HELP;
|
|||
}
|
||||
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Cache Driver Name: ' . $this->cacheDriverName);
|
||||
$this->out('Cache Driver Name: ' . (string)$this->cache);
|
||||
$this->out('Cache Driver Class: ' . get_class($this->cache));
|
||||
}
|
||||
|
||||
|
@ -127,7 +124,7 @@ HELP;
|
|||
private function executeList()
|
||||
{
|
||||
$prefix = $this->getArgument(1);
|
||||
$keys = $this->cache->getAllKeys($prefix);
|
||||
$keys = $this->cache->getAllKeys($prefix);
|
||||
|
||||
if (empty($prefix)) {
|
||||
$this->out('Listing all cache keys:');
|
||||
|
@ -147,7 +144,7 @@ HELP;
|
|||
private function executeGet()
|
||||
{
|
||||
if (count($this->args) >= 2) {
|
||||
$key = $this->getArgument(1);
|
||||
$key = $this->getArgument(1);
|
||||
$value = $this->cache->get($key);
|
||||
|
||||
$this->out("{$key} => " . var_export($value, true));
|
||||
|
@ -159,8 +156,8 @@ HELP;
|
|||
private function executeSet()
|
||||
{
|
||||
if (count($this->args) >= 3) {
|
||||
$key = $this->getArgument(1);
|
||||
$value = $this->getArgument(2);
|
||||
$key = $this->getArgument(1);
|
||||
$value = $this->getArgument(2);
|
||||
$duration = intval($this->getArgument(3, ICache::FIVE_MINUTES));
|
||||
|
||||
if (is_array($this->cache->get($key))) {
|
||||
|
|
|
@ -153,4 +153,9 @@ class APCuCache extends AbstractCache implements IMemoryCache
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return self::TYPE_APCU;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,20 @@ namespace Friendica\Core\Cache;
|
|||
*/
|
||||
abstract class AbstractCache implements ICache
|
||||
{
|
||||
const TYPE_APCU = 'apcu';
|
||||
const TYPE_ARRAY = 'array';
|
||||
const TYPE_DATABASE = 'database';
|
||||
const TYPE_MEMCACHE = 'memcache';
|
||||
const TYPE_MEMCACHED = 'memcached';
|
||||
const TYPE_REDIS = 'redis';
|
||||
|
||||
/**
|
||||
* Force each Cache implementation to define the ToString method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract function __toString();
|
||||
|
||||
/**
|
||||
* @var string The hostname
|
||||
*/
|
||||
|
|
|
@ -92,4 +92,9 @@ class ArrayCache extends AbstractCache implements IMemoryCache
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return self::TYPE_ARRAY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,4 +110,9 @@ class DatabaseCache extends AbstractCache implements ICache
|
|||
return $this->dba->delete('cache', ['`k` IS NOT NULL ']);
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return self::TYPE_DATABASE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,4 +148,9 @@ class MemcacheCache extends AbstractCache implements IMemoryCache
|
|||
$cachekey = $this->getCacheKey($key);
|
||||
return $this->memcache->add($cachekey, serialize($value), MEMCACHE_COMPRESSED, $ttl);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return self::TYPE_MEMCACHE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,4 +151,9 @@ class MemcachedCache extends AbstractCache implements IMemoryCache
|
|||
$cachekey = $this->getCacheKey($key);
|
||||
return $this->memcached->add($cachekey, $value, $ttl);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return self::TYPE_MEMCACHED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,4 +152,9 @@ class ProfilerCache implements ICache, IMemoryCache
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return (string)$this->cache . ' (with profiler)';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,4 +192,9 @@ class RedisCache extends AbstractCache implements IMemoryCache
|
|||
$this->redis->unwatch();
|
||||
return false;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return self::TYPE_REDIS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Friendica\Core\Lock;
|
|||
use Friendica\Core\Cache;
|
||||
use Friendica\Core\Cache\IMemoryCache;
|
||||
|
||||
class CacheLockDriver extends AbstractLock
|
||||
class CacheLock extends AbstractLock
|
||||
{
|
||||
/**
|
||||
* @var \Friendica\Core\Cache\ICache;
|
||||
|
@ -13,7 +13,7 @@ class CacheLockDriver extends AbstractLock
|
|||
private $cache;
|
||||
|
||||
/**
|
||||
* CacheLockDriver constructor.
|
||||
* CacheLock constructor.
|
||||
*
|
||||
* @param IMemoryCache $cache The CacheDriver for this type of lock
|
||||
*/
|
|
@ -11,18 +11,18 @@ use Friendica\Util\Profiler;
|
|||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Class CacheDriverFactory
|
||||
* Class CacheFactory
|
||||
*
|
||||
* @package Friendica\Core\Cache
|
||||
*
|
||||
* A basic class to generate a CacheDriver
|
||||
*/
|
||||
class CacheDriverFactory
|
||||
class CacheFactory
|
||||
{
|
||||
/**
|
||||
* @var string The default driver for caching
|
||||
* @var string The default cache if nothing set
|
||||
*/
|
||||
const DEFAULT_DRIVER = 'database';
|
||||
const DEFAULT_TYPE = Cache\AbstractCache::TYPE_DATABASE;
|
||||
|
||||
/**
|
||||
* @var Configuration The configuration to read parameters out of the config
|
||||
|
@ -52,33 +52,37 @@ class CacheDriverFactory
|
|||
public function __construct(BaseURL $baseURL, Configuration $config, Database $dba, Profiler $profiler, LoggerInterface $logger)
|
||||
{
|
||||
$this->hostname = $baseURL->getHostname();
|
||||
$this->config = $config;
|
||||
$this->dba = $dba;
|
||||
$this->config = $config;
|
||||
$this->dba = $dba;
|
||||
$this->profiler = $profiler;
|
||||
$this->logger = $logger;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a CacheDriver for the given cache driver name
|
||||
*
|
||||
* @param string $type The cache type to create (default is per config)
|
||||
*
|
||||
* @return ICache The instance of the CacheDriver
|
||||
* @throws \Exception The exception if something went wrong during the CacheDriver creation
|
||||
*/
|
||||
public function create()
|
||||
public function create(string $type = null)
|
||||
{
|
||||
$driver = $this->config->get('system', 'cache_driver', self::DEFAULT_DRIVER);
|
||||
if (empty($type)) {
|
||||
$type = $this->config->get('system', 'cache_driver', self::DEFAULT_TYPE);
|
||||
}
|
||||
|
||||
switch ($driver) {
|
||||
case 'memcache':
|
||||
switch ($type) {
|
||||
case Cache\AbstractCache::TYPE_MEMCACHE:
|
||||
$cache = new Cache\MemcacheCache($this->hostname, $this->config);
|
||||
break;
|
||||
case 'memcached':
|
||||
case Cache\AbstractCache::TYPE_MEMCACHED:
|
||||
$cache = new Cache\MemcachedCache($this->hostname, $this->config, $this->logger);
|
||||
break;
|
||||
case 'redis':
|
||||
case Cache\AbstractCache::TYPE_REDIS:
|
||||
$cache = new Cache\RedisCache($this->hostname, $this->config);
|
||||
break;
|
||||
case 'apcu':
|
||||
case Cache\AbstractCache::TYPE_APCU:
|
||||
$cache = new Cache\APCuCache($this->hostname);
|
||||
break;
|
||||
default:
|
||||
|
@ -89,7 +93,7 @@ class CacheDriverFactory
|
|||
|
||||
// In case profiling is enabled, wrap the ProfilerCache around the current cache
|
||||
if (isset($profiling) && $profiling !== false) {
|
||||
return new Cache\ProfilerCache($cache, $this->profiler);
|
||||
return new Cache\ProfilerCache($cache, $this->profiler);
|
||||
} else {
|
||||
return $cache;
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Friendica\Factory;
|
||||
|
||||
use Friendica\Core\Cache\ICache;
|
||||
use Friendica\Core\Cache\AbstractCache;
|
||||
use Friendica\Core\Cache\IMemoryCache;
|
||||
use Friendica\Core\Config\Configuration;
|
||||
use Friendica\Core\Lock;
|
||||
|
@ -11,13 +11,13 @@ use Friendica\Util\Profiler;
|
|||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Class LockDriverFactory
|
||||
* Class LockFactory
|
||||
*
|
||||
* @package Friendica\Core\Cache
|
||||
*
|
||||
* A basic class to generate a LockDriver
|
||||
*/
|
||||
class LockDriverFactory
|
||||
class LockFactory
|
||||
{
|
||||
/**
|
||||
* @var string The default driver for caching
|
||||
|
@ -35,9 +35,9 @@ class LockDriverFactory
|
|||
private $dba;
|
||||
|
||||
/**
|
||||
* @var ICache The memory cache driver in case we use it
|
||||
* @var CacheFactory The memory cache driver in case we use it
|
||||
*/
|
||||
private $cacheDriver;
|
||||
private $cacheFactory;
|
||||
|
||||
/**
|
||||
* @var Profiler The optional profiler if the cached should be profiled
|
||||
|
@ -49,25 +49,29 @@ class LockDriverFactory
|
|||
*/
|
||||
private $logger;
|
||||
|
||||
public function __construct(ICache $cacheDriver, Configuration $config, Database $dba, Profiler $profiler, LoggerInterface $logger)
|
||||
public function __construct(CacheFactory $cacheFactory, Configuration $config, Database $dba, Profiler $profiler, LoggerInterface $logger)
|
||||
{
|
||||
$this->cacheDriver = $cacheDriver;
|
||||
$this->config = $config;
|
||||
$this->dba = $dba;
|
||||
$this->logger = $logger;
|
||||
$this->cacheFactory = $cacheFactory;
|
||||
$this->config = $config;
|
||||
$this->dba = $dba;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$lock_driver = $this->config->get('system', 'lock_driver', self::DEFAULT_DRIVER);
|
||||
$lock_type = $this->config->get('system', 'lock_driver', self::DEFAULT_DRIVER);
|
||||
|
||||
try {
|
||||
switch ($lock_driver) {
|
||||
case 'memcache':
|
||||
case 'memcached':
|
||||
case 'redis':
|
||||
if ($this->cacheDriver instanceof IMemoryCache) {
|
||||
return new Lock\CacheLockDriver($this->cacheDriver);
|
||||
switch ($lock_type) {
|
||||
case AbstractCache::TYPE_MEMCACHE:
|
||||
case AbstractCache::TYPE_MEMCACHED:
|
||||
case AbstractCache::TYPE_REDIS:
|
||||
case AbstractCache::TYPE_APCU:
|
||||
$cache = $this->cacheFactory->create($lock_type);
|
||||
if ($cache instanceof IMemoryCache) {
|
||||
return new Lock\CacheLock($cache);
|
||||
} else {
|
||||
throw new \Exception(sprintf('Incompatible cache driver \'%s\' for lock used', $lock_type));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -83,7 +87,7 @@ class LockDriverFactory
|
|||
return self::useAutoDriver();
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
$this->logger->alert('Driver \'' . $lock_driver . '\' failed - Fallback to \'useAutoDriver()\'', ['exception' => $exception]);
|
||||
$this->logger->alert('Driver \'' . $lock_type . '\' failed - Fallback to \'useAutoDriver()\'', ['exception' => $exception]);
|
||||
return self::useAutoDriver();
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +104,6 @@ class LockDriverFactory
|
|||
*/
|
||||
private function useAutoDriver()
|
||||
{
|
||||
|
||||
// 1. Try to use Semaphores for - local - locking
|
||||
if (function_exists('sem_get')) {
|
||||
try {
|
||||
|
@ -111,11 +114,12 @@ class LockDriverFactory
|
|||
}
|
||||
|
||||
// 2. Try to use Cache Locking (don't use the DB-Cache Locking because it works different!)
|
||||
$cache_driver = $this->config->get('system', 'cache_driver', 'database');
|
||||
if ($cache_driver != 'database') {
|
||||
$cache_type = $this->config->get('system', 'cache_driver', 'database');
|
||||
if ($cache_type != AbstractCache::TYPE_DATABASE) {
|
||||
try {
|
||||
if ($this->cacheDriver instanceof IMemoryCache) {
|
||||
return new Lock\CacheLockDriver($this->cacheDriver);
|
||||
$cache = $this->cacheFactory->create($cache_type);
|
||||
if ($cache instanceof IMemoryCache) {
|
||||
return new Lock\CacheLock($cache);
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
$this->logger->debug('Using Cache driver for locking failed.', ['exception' => $exception]);
|
|
@ -119,16 +119,19 @@ return [
|
|||
]
|
||||
],
|
||||
Cache\ICache::class => [
|
||||
'instanceOf' => Factory\CacheDriverFactory::class,
|
||||
'instanceOf' => Factory\CacheFactory::class,
|
||||
'call' => [
|
||||
['create', [], Dice::CHAIN_CALL],
|
||||
],
|
||||
],
|
||||
Cache\IMemoryCache::class => [
|
||||
'instanceOf' => Cache\ICache::class,
|
||||
'instanceOf' => Factory\CacheFactory::class,
|
||||
'call' => [
|
||||
['create', [], Dice::CHAIN_CALL],
|
||||
],
|
||||
],
|
||||
ILock::class => [
|
||||
'instanceOf' => Factory\LockDriverFactory::class,
|
||||
'instanceOf' => Factory\LockFactory::class,
|
||||
'call' => [
|
||||
['create', [], Dice::CHAIN_CALL],
|
||||
],
|
||||
|
|
|
@ -4,8 +4,11 @@ namespace functional;
|
|||
|
||||
use Dice\Dice;
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Cache\ICache;
|
||||
use Friendica\Core\Cache\IMemoryCache;
|
||||
use Friendica\Core\Config\Cache\ConfigCache;
|
||||
use Friendica\Core\Config\Configuration;
|
||||
use Friendica\Core\Lock\ILock;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Test\Util\VFSTrait;
|
||||
use Friendica\Util\BasePath;
|
||||
|
@ -133,6 +136,31 @@ class dependencyCheck extends TestCase
|
|||
/** @var LoggerInterface $logger */
|
||||
$logger = $this->dice->create('$devLogger', ['dev']);
|
||||
|
||||
self::assertInstanceOf(LoggerInterface::class, $logger);
|
||||
$this->assertInstanceOf(LoggerInterface::class, $logger);
|
||||
}
|
||||
|
||||
public function testCache()
|
||||
{
|
||||
/** @var ICache $cache */
|
||||
$cache = $this->dice->create(ICache::class);
|
||||
|
||||
$this->assertInstanceOf(ICache::class, $cache);
|
||||
}
|
||||
|
||||
public function testMemoryCache()
|
||||
{
|
||||
/** @var IMemoryCache $cache */
|
||||
$cache = $this->dice->create(IMemoryCache::class);
|
||||
|
||||
// We need to check "just" ICache, because the default Cache is DB-Cache, which isn't a memorycache
|
||||
$this->assertInstanceOf(ICache::class, $cache);
|
||||
}
|
||||
|
||||
public function testLock()
|
||||
{
|
||||
/** @var ILock $cache */
|
||||
$lock = $this->dice->create(ILock::class);
|
||||
|
||||
$this->assertInstanceOf(ILock::class, $lock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Friendica\Test\src\Core\Lock;
|
||||
|
||||
use Friendica\Core\Cache\APCuCache;
|
||||
use Friendica\Core\Lock\CacheLockDriver;
|
||||
use Friendica\Core\Lock\CacheLock;
|
||||
|
||||
class APCuCacheLockTest extends LockTest
|
||||
{
|
||||
|
@ -18,6 +18,6 @@ class APCuCacheLockTest extends LockTest
|
|||
|
||||
protected function getInstance()
|
||||
{
|
||||
return new CacheLockDriver(new APCuCache('localhost'));
|
||||
return new CacheLock(new APCuCache('localhost'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
namespace Friendica\Test\src\Core\Lock;
|
||||
|
||||
use Friendica\Core\Cache\ArrayCache;
|
||||
use Friendica\Core\Lock\CacheLockDriver;
|
||||
use Friendica\Core\Lock\CacheLock;
|
||||
|
||||
class ArrayCacheLockTest extends LockTest
|
||||
{
|
||||
protected function getInstance()
|
||||
{
|
||||
return new CacheLockDriver(new ArrayCache('localhost'));
|
||||
return new CacheLock(new ArrayCache('localhost'));
|
||||
}
|
||||
|
||||
public function testLockTTL()
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Friendica\Test\src\Core\Lock;
|
|||
|
||||
use Friendica\Core\Cache\MemcacheCache;
|
||||
use Friendica\Core\Config\Configuration;
|
||||
use Friendica\Core\Lock\CacheLockDriver;
|
||||
use Friendica\Core\Lock\CacheLock;
|
||||
|
||||
/**
|
||||
* @requires extension Memcache
|
||||
|
@ -25,6 +25,6 @@ class MemcacheCacheLockTest extends LockTest
|
|||
->with('system', 'memcache_port')
|
||||
->andReturn(11211);
|
||||
|
||||
return new CacheLockDriver(new MemcacheCache('localhost', $configMock));
|
||||
return new CacheLock(new MemcacheCache('localhost', $configMock));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Friendica\Test\src\Core\Lock;
|
|||
|
||||
use Friendica\Core\Cache\MemcachedCache;
|
||||
use Friendica\Core\Config\Configuration;
|
||||
use Friendica\Core\Lock\CacheLockDriver;
|
||||
use Friendica\Core\Lock\CacheLock;
|
||||
use Psr\Log\NullLogger;
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,6 @@ class MemcachedCacheLockTest extends LockTest
|
|||
|
||||
$logger = new NullLogger();
|
||||
|
||||
return new CacheLockDriver(new MemcachedCache('localhost', $configMock, $logger));
|
||||
return new CacheLock(new MemcachedCache('localhost', $configMock, $logger));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Friendica\Test\src\Core\Lock;
|
|||
|
||||
use Friendica\Core\Cache\RedisCache;
|
||||
use Friendica\Core\Config\Configuration;
|
||||
use Friendica\Core\Lock\CacheLockDriver;
|
||||
use Friendica\Core\Lock\CacheLock;
|
||||
|
||||
/**
|
||||
* @requires extension redis
|
||||
|
@ -34,6 +34,6 @@ class RedisCacheLockTest extends LockTest
|
|||
->with('system', 'redis_password')
|
||||
->andReturn(null);
|
||||
|
||||
return new CacheLockDriver(new RedisCache('localhost', $configMock));
|
||||
return new CacheLock(new RedisCache('localhost', $configMock));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue