mirror of
https://github.com/shlinkio/shlink.git
synced 2025-03-28 20:41:41 +03:00
Merge pull request #445 from acelaya/feature/redis-missings
Feature/redis missings
This commit is contained in:
commit
8484449d66
8 changed files with 105 additions and 19 deletions
|
@ -2,6 +2,7 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Shlinkio\Shlink\Common\Cache\RedisFactory;
|
use Shlinkio\Shlink\Common\Cache\RedisFactory;
|
||||||
|
use Shlinkio\Shlink\Common\Lock\RetryLockStoreDelegatorFactory;
|
||||||
use Symfony\Component\Lock;
|
use Symfony\Component\Lock;
|
||||||
use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory;
|
use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory;
|
||||||
|
|
||||||
|
@ -22,6 +23,11 @@ return [
|
||||||
'lock_store' => Lock\Store\FlockStore::class,
|
'lock_store' => Lock\Store\FlockStore::class,
|
||||||
'redis_lock_store' => Lock\Store\RedisStore::class,
|
'redis_lock_store' => Lock\Store\RedisStore::class,
|
||||||
],
|
],
|
||||||
|
'delegators' => [
|
||||||
|
Lock\Store\RedisStore::class => [
|
||||||
|
RetryLockStoreDelegatorFactory::class,
|
||||||
|
],
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
ConfigAbstractFactory::class => [
|
ConfigAbstractFactory::class => [
|
||||||
|
|
|
@ -26,5 +26,5 @@ return (new ConfigAggregator\ConfigAggregator([
|
||||||
? new ConfigAggregator\PhpFileProvider('config/test/*.global.php')
|
? new ConfigAggregator\PhpFileProvider('config/test/*.global.php')
|
||||||
: new ConfigAggregator\ZendConfigProvider('config/params/{generated_config.php,*.config.{php,json}}'),
|
: new ConfigAggregator\ZendConfigProvider('config/params/{generated_config.php,*.config.{php,json}}'),
|
||||||
], 'data/cache/app_config.php', [
|
], 'data/cache/app_config.php', [
|
||||||
Core\ConfigPostProcessor::class,
|
Core\SimplifiedConfigParser::class,
|
||||||
]))->getMergedConfig();
|
]))->getMergedConfig();
|
||||||
|
|
|
@ -6,9 +6,8 @@ namespace Shlinkio\Shlink\Common\Cache;
|
||||||
use Predis\Client as PredisClient;
|
use Predis\Client as PredisClient;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
use function array_shift;
|
|
||||||
use function count;
|
use function count;
|
||||||
use function is_array;
|
use function explode;
|
||||||
use function is_string;
|
use function is_string;
|
||||||
|
|
||||||
class RedisFactory
|
class RedisFactory
|
||||||
|
@ -18,13 +17,11 @@ class RedisFactory
|
||||||
public function __invoke(ContainerInterface $container): PredisClient
|
public function __invoke(ContainerInterface $container): PredisClient
|
||||||
{
|
{
|
||||||
$redisConfig = $container->get('config')['redis'] ?? [];
|
$redisConfig = $container->get('config')['redis'] ?? [];
|
||||||
|
|
||||||
$servers = $redisConfig['servers'] ?? [];
|
$servers = $redisConfig['servers'] ?? [];
|
||||||
|
$servers = is_string($servers) ? explode(',', $servers) : $servers;
|
||||||
|
$options = count($servers) <= 1 ? null : ['cluster' => 'redis'];
|
||||||
|
|
||||||
if (is_array($servers) && count($servers) === 1) {
|
|
||||||
$servers = array_shift($servers);
|
|
||||||
}
|
|
||||||
|
|
||||||
$options = is_string($servers) || count($servers) < 1 ? null : ['cluster' => 'redis'];
|
|
||||||
return new PredisClient($servers, $options);
|
return new PredisClient($servers, $options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
module/Common/src/Lock/RetryLockStoreDelegatorFactory.php
Normal file
18
module/Common/src/Lock/RetryLockStoreDelegatorFactory.php
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Common\Lock;
|
||||||
|
|
||||||
|
use Interop\Container\ContainerInterface;
|
||||||
|
use Symfony\Component\Lock\Store\RetryTillSaveStore;
|
||||||
|
use Symfony\Component\Lock\StoreInterface;
|
||||||
|
|
||||||
|
class RetryLockStoreDelegatorFactory
|
||||||
|
{
|
||||||
|
public function __invoke(ContainerInterface $container, $name, callable $callback): RetryTillSaveStore
|
||||||
|
{
|
||||||
|
/** @var StoreInterface $originalStore */
|
||||||
|
$originalStore = $callback();
|
||||||
|
return new RetryTillSaveStore($originalStore);
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,5 +54,8 @@ class RedisFactoryTest extends TestCase
|
||||||
yield 'empty cluster of servers' => [[
|
yield 'empty cluster of servers' => [[
|
||||||
'servers' => [],
|
'servers' => [],
|
||||||
], PredisCluster::class];
|
], PredisCluster::class];
|
||||||
|
yield 'cluster of servers as string' => [[
|
||||||
|
'servers' => 'tcp://1.1.1.1:6379,tcp://2.2.2.2:6379',
|
||||||
|
], RedisCluster::class];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ShlinkioTest\Shlink\Common\Lock;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Prophecy\Prophecy\ObjectProphecy;
|
||||||
|
use ReflectionObject;
|
||||||
|
use Shlinkio\Shlink\Common\Lock\RetryLockStoreDelegatorFactory;
|
||||||
|
use Symfony\Component\Lock\StoreInterface;
|
||||||
|
use Zend\ServiceManager\ServiceManager;
|
||||||
|
|
||||||
|
class RetryLockStoreDelegatorFactoryTest extends TestCase
|
||||||
|
{
|
||||||
|
/** @var RetryLockStoreDelegatorFactory */
|
||||||
|
private $delegator;
|
||||||
|
/** @var ObjectProphecy */
|
||||||
|
private $originalStore;
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->originalStore = $this->prophesize(StoreInterface::class)->reveal();
|
||||||
|
$this->delegator = new RetryLockStoreDelegatorFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function originalStoreIsWrappedInRetryStore(): void
|
||||||
|
{
|
||||||
|
$callback = function () {
|
||||||
|
return $this->originalStore;
|
||||||
|
};
|
||||||
|
|
||||||
|
$result = ($this->delegator)(new ServiceManager(), '', $callback);
|
||||||
|
|
||||||
|
$ref = new ReflectionObject($result);
|
||||||
|
$prop = $ref->getProperty('decorated');
|
||||||
|
$prop->setAccessible(true);
|
||||||
|
|
||||||
|
$this->assertSame($this->originalStore, $prop->getValue($result));
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ use function array_key_exists;
|
||||||
use function Functional\contains;
|
use function Functional\contains;
|
||||||
use function Functional\reduce_left;
|
use function Functional\reduce_left;
|
||||||
|
|
||||||
class ConfigPostProcessor
|
class SimplifiedConfigParser
|
||||||
{
|
{
|
||||||
private const SIMPLIFIED_CONFIG_MAPPING = [
|
private const SIMPLIFIED_CONFIG_MAPPING = [
|
||||||
'disable_track_param' => ['app_options', 'disable_track_param'],
|
'disable_track_param' => ['app_options', 'disable_track_param'],
|
||||||
|
@ -22,11 +22,21 @@ class ConfigPostProcessor
|
||||||
'db_config' => ['entity_manager', 'connection'],
|
'db_config' => ['entity_manager', 'connection'],
|
||||||
'delete_short_url_threshold' => ['delete_short_urls', 'visits_threshold'],
|
'delete_short_url_threshold' => ['delete_short_urls', 'visits_threshold'],
|
||||||
'locale' => ['translator', 'locale'],
|
'locale' => ['translator', 'locale'],
|
||||||
'lock_store' => ['dependencies', 'aliases', 'lock_store'],
|
'redis_servers' => ['redis', 'servers'],
|
||||||
];
|
];
|
||||||
private const SIMPLIFIED_CONFIG_TOGGLES = [
|
private const SIMPLIFIED_CONFIG_SIDE_EFFECTS = [
|
||||||
'not_found_redirect_to' => ['url_shortener', 'not_found_short_url', 'enable_redirection'],
|
'not_found_redirect_to' => [
|
||||||
'delete_short_url_threshold' => ['delete_short_urls', 'check_visits_threshold'],
|
'path' => ['url_shortener', 'not_found_short_url', 'enable_redirection'],
|
||||||
|
'value' => true,
|
||||||
|
],
|
||||||
|
'delete_short_url_threshold' => [
|
||||||
|
'path' => ['delete_short_urls', 'check_visits_threshold'],
|
||||||
|
'value' => true,
|
||||||
|
],
|
||||||
|
'redis_servers' => [
|
||||||
|
'path' => ['dependencies', 'aliases', 'lock_store'],
|
||||||
|
'value' => 'redis_lock_store',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
private const SIMPLIFIED_MERGEABLE_CONFIG = ['db_config'];
|
private const SIMPLIFIED_MERGEABLE_CONFIG = ['db_config'];
|
||||||
|
|
||||||
|
@ -41,8 +51,9 @@ class ConfigPostProcessor
|
||||||
}
|
}
|
||||||
|
|
||||||
$collection->setValueInPath($value, $path);
|
$collection->setValueInPath($value, $path);
|
||||||
if (array_key_exists($key, self::SIMPLIFIED_CONFIG_TOGGLES)) {
|
if (array_key_exists($key, self::SIMPLIFIED_CONFIG_SIDE_EFFECTS)) {
|
||||||
$collection->setValueInPath(true, self::SIMPLIFIED_CONFIG_TOGGLES[$key]);
|
['path' => $sideEffectPath, 'value' => $sideEffectValue] = self::SIMPLIFIED_CONFIG_SIDE_EFFECTS[$key];
|
||||||
|
$collection->setValueInPath($sideEffectValue, $sideEffectPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $collection;
|
return $collection;
|
|
@ -4,17 +4,17 @@ declare(strict_types=1);
|
||||||
namespace ShlinkioTest\Shlink\Core;
|
namespace ShlinkioTest\Shlink\Core;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Shlinkio\Shlink\Core\ConfigPostProcessor;
|
use Shlinkio\Shlink\Core\SimplifiedConfigParser;
|
||||||
|
|
||||||
use function array_merge;
|
use function array_merge;
|
||||||
|
|
||||||
class ConfigPostProcessorTest extends TestCase
|
class SimplifiedConfigParserTest extends TestCase
|
||||||
{
|
{
|
||||||
private $postProcessor;
|
private $postProcessor;
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
$this->postProcessor = new ConfigPostProcessor();
|
$this->postProcessor = new SimplifiedConfigParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
@ -41,7 +41,10 @@ class ConfigPostProcessorTest extends TestCase
|
||||||
'delete_short_url_threshold' => 50,
|
'delete_short_url_threshold' => 50,
|
||||||
'locale' => 'es',
|
'locale' => 'es',
|
||||||
'not_found_redirect_to' => 'foobar.com',
|
'not_found_redirect_to' => 'foobar.com',
|
||||||
'lock_store' => 'redis_lock_store',
|
'redis_servers' => [
|
||||||
|
'tcp://1.1.1.1:1111',
|
||||||
|
'tcp://1.2.2.2:2222',
|
||||||
|
],
|
||||||
'db_config' => [
|
'db_config' => [
|
||||||
'dbname' => 'shlink',
|
'dbname' => 'shlink',
|
||||||
'user' => 'foo',
|
'user' => 'foo',
|
||||||
|
@ -91,6 +94,13 @@ class ConfigPostProcessorTest extends TestCase
|
||||||
'lock_store' => 'redis_lock_store',
|
'lock_store' => 'redis_lock_store',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'redis' => [
|
||||||
|
'servers' => [
|
||||||
|
'tcp://1.1.1.1:1111',
|
||||||
|
'tcp://1.2.2.2:2222',
|
||||||
|
],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
$result = ($this->postProcessor)(array_merge($config, $simplified));
|
$result = ($this->postProcessor)(array_merge($config, $simplified));
|
Loading…
Add table
Reference in a new issue