minor #28691 [Cache] add RedisClusterProxy to create lazy connections to Redis clusters (alekitto)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[Cache] add RedisClusterProxy to create lazy connections to Redis clusters

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

Code provided by @alekitto in #28300
I'm working on an alternative to this PR, but these bits are required.

Commits
-------

239a022cc0 [Cache] add RedisClusterProxy to create lazy connections to Redis clusters
This commit is contained in:
Nicolas Grekas 2018-10-02 21:16:25 +02:00
commit 38655bd054
5 changed files with 85 additions and 6 deletions

View File

@ -0,0 +1,63 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Cache\Traits;
/**
* @author Alessandro Chitolina <alekitto@gmail.com>
*
* @internal
*/
class RedisClusterProxy
{
private $redis;
private $initializer;
public function __construct(\Closure $initializer)
{
$this->initializer = $initializer;
}
public function __call($method, array $args)
{
$this->redis ?: $this->redis = $this->initializer->__invoke();
return $this->redis->{$method}(...$args);
}
public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null)
{
$this->redis ?: $this->redis = $this->initializer->__invoke();
return $this->redis->hscan($strKey, $iIterator, $strPattern, $iCount);
}
public function scan(&$iIterator, $strPattern = null, $iCount = null)
{
$this->redis ?: $this->redis = $this->initializer->__invoke();
return $this->redis->scan($iIterator, $strPattern, $iCount);
}
public function sscan($strKey, &$iIterator, $strPattern = null, $iCount = null)
{
$this->redis ?: $this->redis = $this->initializer->__invoke();
return $this->redis->sscan($strKey, $iIterator, $strPattern, $iCount);
}
public function zscan($strKey, &$iIterator, $strPattern = null, $iCount = null)
{
$this->redis ?: $this->redis = $this->initializer->__invoke();
return $this->redis->zscan($strKey, $iIterator, $strPattern, $iCount);
}
}

View File

@ -52,7 +52,7 @@ trait RedisTrait
if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) {
throw new InvalidArgumentException(sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
}
if (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \RedisCluster && !$redisClient instanceof \Predis\Client && !$redisClient instanceof RedisProxy) {
if (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \RedisCluster && !$redisClient instanceof \Predis\Client && !$redisClient instanceof RedisProxy && !$redisClient instanceof RedisClusterProxy) {
throw new InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, %s given', __METHOD__, \is_object($redisClient) ? \get_class($redisClient) : \gettype($redisClient)));
}
$this->redis = $redisClient;
@ -237,7 +237,7 @@ trait RedisTrait
foreach ($this->redis->_hosts() as $host) {
$hosts[] = $this->redis->_instance($host);
}
} elseif ($this->redis instanceof \RedisCluster) {
} elseif ($this->redis instanceof RedisClusterProxy || $this->redis instanceof \RedisCluster) {
$hosts = array();
foreach ($this->redis->_masters() as $host) {
$hosts[] = $h = new \Redis();
@ -330,7 +330,7 @@ trait RedisTrait
{
$ids = array();
if ($this->redis instanceof \RedisCluster || ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof RedisCluster)) {
if ($this->redis instanceof RedisClusterProxy || $this->redis instanceof \RedisCluster || ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof RedisCluster)) {
// phpredis & predis don't support pipelining with RedisCluster
// see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining
// see https://github.com/nrk/predis/issues/267#issuecomment-123781423

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
use Predis\Response\ErrorInterface;
use Symfony\Component\Cache\Traits\RedisClusterProxy;
use Symfony\Component\Cache\Traits\RedisProxy;
/**
@ -45,7 +46,8 @@ class RedisSessionHandler extends AbstractSessionHandler
!$redis instanceof \RedisArray &&
!$redis instanceof \RedisCluster &&
!$redis instanceof \Predis\Client &&
!$redis instanceof RedisProxy
!$redis instanceof RedisProxy &&
!$redis instanceof RedisClusterProxy
) {
throw new \InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, %s given', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis)));
}

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Lock\Store;
use Symfony\Component\Cache\Traits\RedisClusterProxy;
use Symfony\Component\Cache\Traits\RedisProxy;
use Symfony\Component\Lock\Exception\InvalidArgumentException;
use Symfony\Component\Lock\Exception\LockConflictedException;
@ -130,7 +131,12 @@ class RedisStore implements StoreInterface
*/
private function evaluate(string $script, string $resource, array $args)
{
if ($this->redis instanceof \Redis || $this->redis instanceof \RedisCluster || $this->redis instanceof RedisProxy) {
if (
$this->redis instanceof \Redis ||
$this->redis instanceof \RedisCluster ||
$this->redis instanceof RedisProxy ||
$this->redis instanceof RedisClusterProxy
) {
return $this->redis->eval($script, array_merge(array($resource), $args), 1);
}

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Lock\Store;
use Symfony\Component\Cache\Traits\RedisClusterProxy;
use Symfony\Component\Cache\Traits\RedisProxy;
use Symfony\Component\Lock\Exception\InvalidArgumentException;
@ -28,7 +29,14 @@ class StoreFactory
*/
public static function createStore($connection)
{
if ($connection instanceof \Redis || $connection instanceof \RedisArray || $connection instanceof \RedisCluster || $connection instanceof \Predis\Client || $connection instanceof RedisProxy) {
if (
$connection instanceof \Redis ||
$connection instanceof \RedisArray ||
$connection instanceof \RedisCluster ||
$connection instanceof \Predis\Client ||
$connection instanceof RedisProxy ||
$connection instanceof RedisClusterProxy
) {
return new RedisStore($connection);
}
if ($connection instanceof \Memcached) {