Move Cache to strategies

This commit is contained in:
Philipp Holzer 2023-07-22 23:57:38 +02:00
parent f1da323b07
commit f2c02a79b9
Signed by: nupplaPhil
GPG Key ID: 24A7501396EB5432
12 changed files with 98 additions and 119 deletions

View File

@ -21,16 +21,14 @@
namespace Friendica\Core\Cache\Factory;
use Friendica\App\BaseURL;
use Friendica\Core\Cache\Enum;
use Friendica\Core\Cache\Capability\ICanCache;
use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Cache\Type;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Database\Database;
use Friendica\Core\Hooks\Capabilities\ICanCreateInstances;
use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface;
/**
* Class CacheFactory
@ -45,39 +43,18 @@ class Cache
* @var string The default cache if nothing set
*/
const DEFAULT_TYPE = Enum\Type::DATABASE;
/** @var ICanCreateInstances */
protected $instanceCreator;
/** @var IManageConfigValues */
protected $config;
/** @var Profiler */
protected $profiler;
/**
* @var IManageConfigValues The IConfiguration to read parameters out of the config
*/
private $config;
/**
* @var Database The database connection in case that the cache is used the dba connection
*/
private $dba;
/**
* @var string The hostname, used as Prefix for Caching
*/
private $hostname;
/**
* @var Profiler The optional profiler if the cached should be profiled
*/
private $profiler;
/**
* @var LoggerInterface The Friendica Logger
*/
private $logger;
public function __construct(BaseURL $baseURL, IManageConfigValues $config, Database $dba, Profiler $profiler, LoggerInterface $logger)
public function __construct(ICanCreateInstances $instanceCreator, IManageConfigValues $config, Profiler $profiler)
{
$this->hostname = $baseURL->getHost();
$this->config = $config;
$this->dba = $dba;
$this->profiler = $profiler;
$this->logger = $logger;
$this->config = $config;
$this->instanceCreator = $instanceCreator;
$this->profiler = $profiler;
}
/**
@ -92,7 +69,7 @@ class Cache
*/
public function createDistributed(string $type = null): ICanCache
{
if ($type === Enum\Type::APCU) {
if ($type === Type\APCuCache::$NAME) {
throw new InvalidCacheDriverException('apcu doesn\'t support distributed caching.');
}
@ -117,31 +94,17 @@ class Cache
/**
* Creates a new Cache instance
*
* @param string $type The type of cache
* @param string $strategy The strategy, which cache instance should be used
*
* @return ICanCache
*
* @throws InvalidCacheDriverException In case the underlying cache driver isn't valid or not configured properly
* @throws CachePersistenceException In case the underlying cache has errors during persistence
*/
protected function create(string $type): ICanCache
protected function create(string $strategy): ICanCache
{
switch ($type) {
case Enum\Type::MEMCACHE:
$cache = new Type\MemcacheCache($this->hostname, $this->config);
break;
case Enum\Type::MEMCACHED:
$cache = new Type\MemcachedCache($this->hostname, $this->config, $this->logger);
break;
case Enum\Type::REDIS:
$cache = new Type\RedisCache($this->hostname, $this->config);
break;
case Enum\Type::APCU:
$cache = new Type\APCuCache($this->hostname);
break;
default:
$cache = new Type\DatabaseCache($this->hostname, $this->dba);
}
/** @var ICanCache $cache */
$cache = $this->instanceCreator->create(ICanCache::class, $strategy);
$profiling = $this->config->get('system', 'profiling', false);

View File

@ -23,7 +23,6 @@ namespace Friendica\Core\Cache\Type;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
/**
@ -31,12 +30,12 @@ use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
*/
class APCuCache extends AbstractCache implements ICanCacheInMemory
{
public static $NAME = 'apcu';
use CompareSetTrait;
use CompareDeleteTrait;
/**
* @param string $hostname
*
* @throws InvalidCacheDriverException
*/
public function __construct(string $hostname)
@ -173,12 +172,4 @@ class APCuCache extends AbstractCache implements ICanCacheInMemory
return true;
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::APCU;
}
}

View File

@ -28,6 +28,8 @@ use Friendica\Core\Cache\Capability\ICanCache;
*/
abstract class AbstractCache implements ICanCache
{
public static $NAME = '';
/**
* @var string The hostname
*/
@ -105,4 +107,10 @@ abstract class AbstractCache implements ICanCache
return $result;
}
}
/** {@inheritDoc} */
public function getName(): string
{
return static::$NAME;
}
}

View File

@ -29,6 +29,8 @@ use Friendica\Core\Cache\Enum;
*/
class ArrayCache extends AbstractCache implements ICanCacheInMemory
{
public static $NAME = 'array';
use CompareDeleteTrait;
/** @var array Array with the cached data */
@ -108,12 +110,4 @@ class ArrayCache extends AbstractCache implements ICanCacheInMemory
return false;
}
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Enum\Type::ARRAY;
}
}

View File

@ -32,6 +32,8 @@ use Friendica\Util\DateTimeFormat;
*/
class DatabaseCache extends AbstractCache implements ICanCache
{
public static $NAME = 'database';
/**
* @var Database
*/
@ -154,12 +156,4 @@ class DatabaseCache extends AbstractCache implements ICanCache
throw new CachePersistenceException('Cannot clear cache', $exception);
}
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Enum\Type::DATABASE;
}
}

View File

@ -23,7 +23,6 @@ namespace Friendica\Core\Cache\Type;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Config\Capability\IManageConfigValues;
@ -34,6 +33,8 @@ use Memcache;
*/
class MemcacheCache extends AbstractCache implements ICanCacheInMemory
{
static $NAME = 'memcached';
use CompareSetTrait;
use CompareDeleteTrait;
use MemcacheCommandTrait;
@ -169,12 +170,4 @@ class MemcacheCache extends AbstractCache implements ICanCacheInMemory
$cacheKey = $this->getCacheKey($key);
return $this->memcache->add($cacheKey, serialize($value), MEMCACHE_COMPRESSED, $ttl);
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::MEMCACHE;
}
}

View File

@ -23,7 +23,6 @@ namespace Friendica\Core\Cache\Type;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Config\Capability\IManageConfigValues;
@ -35,6 +34,8 @@ use Psr\Log\LoggerInterface;
*/
class MemcachedCache extends AbstractCache implements ICanCacheInMemory
{
static $NAME = 'memcached';
use CompareSetTrait;
use CompareDeleteTrait;
use MemcacheCommandTrait;
@ -185,12 +186,4 @@ class MemcachedCache extends AbstractCache implements ICanCacheInMemory
$cacheKey = $this->getCacheKey($key);
return $this->memcached->add($cacheKey, $value, $ttl);
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::MEMCACHED;
}
}

View File

@ -21,10 +21,8 @@
namespace Friendica\Core\Cache\Type;
use Exception;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Config\Capability\IManageConfigValues;
@ -35,6 +33,8 @@ use Redis;
*/
class RedisCache extends AbstractCache implements ICanCacheInMemory
{
public static $NAME = 'redis';
/**
* @var Redis
*/
@ -59,18 +59,23 @@ class RedisCache extends AbstractCache implements ICanCacheInMemory
$redis_pw = $config->get('system', 'redis_password');
$redis_db = $config->get('system', 'redis_db', 0);
if (!empty($redis_port) && !@$this->redis->connect($redis_host, $redis_port)) {
throw new CachePersistenceException('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available');
} elseif (!@$this->redis->connect($redis_host)) {
throw new CachePersistenceException('Expected Redis server at ' . $redis_host . ' isn\'t available');
}
try {
if (!empty($redis_pw) && !$this->redis->auth($redis_pw)) {
throw new CachePersistenceException('Cannot authenticate redis server at ' . $redis_host . ':' . $redis_port);
}
if (!empty($redis_port) && !@$this->redis->connect($redis_host, $redis_port)) {
throw new CachePersistenceException('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available');
} else if (!@$this->redis->connect($redis_host)) {
throw new CachePersistenceException('Expected Redis server at ' . $redis_host . ' isn\'t available');
}
if ($redis_db !== 0 && !$this->redis->select($redis_db)) {
throw new CachePersistenceException('Cannot switch to redis db ' . $redis_db . ' at ' . $redis_host . ':' . $redis_port);
if (!empty($redis_pw) && !$this->redis->auth($redis_pw)) {
throw new CachePersistenceException('Cannot authenticate redis server at ' . $redis_host . ':' . $redis_port);
}
if ($redis_db !== 0 && !$this->redis->select($redis_db)) {
throw new CachePersistenceException('Cannot switch to redis db ' . $redis_db . ' at ' . $redis_host . ':' . $redis_port);
}
} catch (\RedisException $exception) {
throw new CachePersistenceException('Redis connection fails unexpectedly', $exception);
}
}
@ -211,12 +216,4 @@ class RedisCache extends AbstractCache implements ICanCacheInMemory
$this->redis->unwatch();
return false;
}
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::REDIS;
}
}

View File

@ -178,6 +178,20 @@ return [
$_SERVER,
],
],
'$hostname' => [
'instanceOf' => App\BaseURL::class,
'constructParams' => [
$_SERVER,
],
'call' => [
['getHost', [], Dice::CHAIN_CALL],
],
],
Cache\Type\AbstractCache::class => [
'constructParams' => [
[Dice::INSTANCE => '$hostname'],
],
],
App\Page::class => [
'constructParams' => [
[Dice::INSTANCE => '$basepath'],

View File

@ -19,7 +19,7 @@
*
*/
use Friendica\Core\Hooks\Capabilities\BehavioralHookType as H;
use Friendica\Core\Cache;
use Friendica\Core\Logger\Type;
use Psr\Log;
@ -29,4 +29,11 @@ return [
Type\SyslogLogger::class => ['syslog'],
Type\StreamLogger::class => ['stream'],
],
Cache\Capability\ICanCache::class => [
Cache\Type\APCuCache::class => ['apcu'],
Cache\Type\DatabaseCache::class => ['database', ''],
Cache\Type\MemcacheCache::class => ['memcache'],
Cache\Type\MemcachedCache::class => ['memcached'],
Cache\Type\RedisCache::class => ['redis'],
]
];

24
tests/phpunit-addons.xml Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="bootstrap.php"
verbose="true"
timeoutForSmallTests="900"
timeoutForMediumTests="900"
timeoutForLargeTests="900"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<testsuite name="friendica-addons">
<directory suffix=".php">../addon/*/tests/</directory>
</testsuite>
<!-- Filters for Code Coverage -->
<coverage>
<include>
<directory suffix=".php">../addon/</directory>
</include>
<exclude>
<directory suffix=".php">../addon/*/tests/</directory>
<directory suffix=".php">../addon/*/view/</directory>
<directory suffix=".php">../addon/*/vendor/</directory>
</exclude>
</coverage>
</phpunit>

View File

@ -21,6 +21,7 @@
namespace Friendica\Test\src\Core\Cache;
use Friendica\App\BaseURL;
use Friendica\Core\Cache;
use Friendica\Test\DatabaseTestTrait;
use Friendica\Test\Util\CreateDatabaseTrait;