[TOOLS] Raise PHPStan level to 5 and fix associated error, fixing some bugs in the process

This commit is contained in:
2022-10-19 22:38:49 +01:00
parent edeee49af9
commit fed2242a56
16 changed files with 139 additions and 108 deletions

View File

@@ -23,7 +23,6 @@ declare(strict_types = 1);
namespace App\Core;
use App\Core\DB;
use App\Entity\Actor;
use App\Entity\LocalUser;
use App\Entity\Note;
@@ -32,6 +31,7 @@ use App\Util\Exception\ConfigurationException;
use App\Util\Exception\NotImplementedException;
use Functional as F;
use InvalidArgumentException;
use Memcached;
use Redis;
use RedisCluster;
use Symfony\Component\Cache\Adapter;
@@ -65,61 +65,66 @@ abstract class Cache
$rest = '';
}
switch ($scheme) {
case 'redis':
// Redis can have multiple servers, but we want to take proper advantage of
// redis, not just as a key value store, but using it's datastructures
$dsns = explode(';', $dsn);
if (\count($dsns) === 1) {
$class = Redis::class;
$r = new Redis();
$r->pconnect($rest);
} else {
// @codeCoverageIgnoreStart
// This requires extra server configuration, but the code was tested
// manually and works, so it'll be excluded from automatic tests, for now, at least
if (F\Every($dsns, function ($str) { [$scheme, $rest] = explode('://', $str); return str_contains($rest, ':'); }) == false) {
throw new ConfigurationException('The configuration of a redis cluster requires specifying the ports to use');
case 'redis':
// Redis can have multiple servers, but we want to take proper advantage of
// redis, not just as a key value store, but using it's datastructures
$dsns = explode(';', $dsn);
if (\count($dsns) === 1) {
$class = Redis::class;
$r = new Redis();
$r->pconnect($rest);
} else {
// @codeCoverageIgnoreStart
// This requires extra server configuration, but the code was tested
// manually and works, so it'll be excluded from automatic tests, for now, at least
if (F\Every($dsns, function ($str) { [$scheme, $rest] = explode('://', $str);
return str_contains($rest, ':'); }) == false) {
throw new ConfigurationException('The configuration of a redis cluster requires specifying the ports to use');
}
$class = RedisCluster::class; // true for persistent connection
$seeds = F\Map($dsns, fn ($str) => explode('://', $str)[1]);
$r = new RedisCluster(name: null, seeds: $seeds, timeout: 0.0, readTimeout: 0.0, persistent: true);
// Distribute reads randomly
$r->setOption($class::OPT_SLAVE_FAILOVER, $class::FAILOVER_DISTRIBUTE);
// @codeCoverageIgnoreEnd
}
$class = RedisCluster::class; // true for persistent connection
$seeds = F\Map($dsns, fn ($str) => explode('://', $str)[1]);
$r = new RedisCluster(name: null, seeds: $seeds, timeout: null, readTimeout: null, persistent: true);
// Distribute reads randomly
$r->setOption($class::OPT_SLAVE_FAILOVER, $class::FAILOVER_DISTRIBUTE);
// Improved serializer
$r->setOption($class::OPT_SERIALIZER, $class::SERIALIZER_MSGPACK);
// Persistent connection
$r->setOption($class::OPT_TCP_KEEPALIVE, true);
// Use LZ4 for the improved decompression speed (while keeping an okay compression ratio)
$r->setOption($class::OPT_COMPRESSION, $class::COMPRESSION_LZ4);
self::$redis[$pool] = $r;
$adapters[$pool][] = new Adapter\RedisAdapter($r);
break;
case 'memcached':
// @codeCoverageIgnoreStart
// These all are excluded from automatic testing, as they require an unreasonable amount
// of configuration in the testing environment. The code is really simple, so it should work
// memcached can also have multiple servers
// host:port:weight?
$dsns = explode(';', $dsn);
$servers = F\map($dsns, fn ($dsn) => explode(':', $dsn));
$memcached = new Memcached();
$memcached->addServers($servers);
$adapters[$pool][] = new Adapter\MemcachedAdapter($memcached);
break;
case 'filesystem':
$adapters[$pool][] = new Adapter\FilesystemAdapter($rest);
break;
case 'apcu':
$adapters[$pool][] = new Adapter\ApcuAdapter();
break;
case 'opcache':
$adapters[$pool][] = new Adapter\PhpArrayAdapter($rest, new Adapter\FilesystemAdapter($rest . '.fallback'));
break;
case 'doctrine':
$adapters[$pool][] = new Adapter\PdoAdapter($dsn);
break;
default:
Log::error("Unknown or discouraged cache scheme '{$scheme}'");
return;
// @codeCoverageIgnoreEnd
}
// Improved serializer
$r->setOption($class::OPT_SERIALIZER, $class::SERIALIZER_MSGPACK);
// Persistent connection
$r->setOption($class::OPT_TCP_KEEPALIVE, true);
// Use LZ4 for the improved decompression speed (while keeping an okay compression ratio)
$r->setOption($class::OPT_COMPRESSION, $class::COMPRESSION_LZ4);
self::$redis[$pool] = $r;
$adapters[$pool][] = new Adapter\RedisAdapter($r);
break;
case 'memcached':
// @codeCoverageIgnoreStart
// These all are excluded from automatic testing, as they require an unreasonable amount
// of configuration in the testing environment. The code is really simple, so it should work
// memcached can also have multiple servers
$dsns = explode(';', $dsn);
$adapters[$pool][] = new Adapter\MemcachedAdapter($dsns);
break;
case 'filesystem':
$adapters[$pool][] = new Adapter\FilesystemAdapter($rest);
break;
case 'apcu':
$adapters[$pool][] = new Adapter\ApcuAdapter();
break;
case 'opcache':
$adapters[$pool][] = new Adapter\PhpArrayAdapter($rest, new Adapter\FilesystemAdapter($rest . '.fallback'));
break;
case 'doctrine':
$adapters[$pool][] = new Adapter\PdoAdapter($dsn);
break;
default:
Log::error("Unknown or discouraged cache scheme '{$scheme}'");
return;
// @codeCoverageIgnoreEnd
}
}
@@ -198,7 +203,7 @@ abstract class Cache
$key,
recompute: function () use ($key, $calculate, $pool) {
$save = true; // Pass by reference
$res = $calculate(null, $save);
$res = $calculate(null, $save);
if ($save) {
self::set($key, $res, $pool);
}
@@ -255,7 +260,7 @@ abstract class Cache
*/
function () use ($key, $calculate, $pool, $max_count, $left, $right, $beta) {
$save = true; // Pass by reference
$res = $calculate(null, $save);
$res = $calculate(null, $save);
if ($save) {
self::setList($key, $res, $pool, $max_count, $beta);
}
@@ -291,7 +296,7 @@ abstract class Cache
*/
function () use ($calculate, $max_count) {
$save = true;
$res = $calculate(null, $save);
$res = $calculate(null, $save);
if ($max_count != -1) {
$res = \array_slice($res, 0, $max_count);
}
@@ -434,6 +439,7 @@ abstract class Cache
* for redis and others. Different from lists, works with string map_keys
*
* @param callable(?CacheItem $item, bool &$save): (string|object|array<string,mixed>) $calculate
*
* @TODO cleanup
*/
public static function getHashMap(string $map_key, callable $calculate, string $pool = 'default', float $beta = 1.0): array
@@ -443,7 +449,7 @@ abstract class Cache
$map_key,
recompute: function () use ($map_key, $calculate, $pool) {
$save = true; // Pass by reference
$res = $calculate(null, $save);
$res = $calculate(null, $save);
if ($save) {
self::setHashMap($map_key, $res, $pool);
}
@@ -531,7 +537,7 @@ abstract class Cache
$getter = fn (int $offset, int $length) => DB::dql($query, $query_args, options: ['offset' => $offset, 'limit' => $length]);
$requested_left = $offset = $per_page * ($page - 1);
$requested_left = $offset = $per_page * ($page - 1);
$requested_right = $requested_left + $per_page;
[$stored_left, $stored_right] = F\map(
explode(':', self::get("{$key}-bounds", fn () => "{$requested_left}:{$requested_right}")),