From 239a022cc01cca52c3f6ddde3231199369cf34c2 Mon Sep 17 00:00:00 2001 From: Alessandro Chitolina Date: Mon, 24 Sep 2018 10:32:31 +0200 Subject: [PATCH] [Cache] add RedisClusterProxy to create lazy connections to Redis clusters --- .../Cache/Traits/RedisClusterProxy.php | 63 +++++++++++++++++++ .../Component/Cache/Traits/RedisTrait.php | 6 +- .../Storage/Handler/RedisSessionHandler.php | 4 +- .../Component/Lock/Store/RedisStore.php | 8 ++- .../Component/Lock/Store/StoreFactory.php | 10 ++- 5 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 src/Symfony/Component/Cache/Traits/RedisClusterProxy.php diff --git a/src/Symfony/Component/Cache/Traits/RedisClusterProxy.php b/src/Symfony/Component/Cache/Traits/RedisClusterProxy.php new file mode 100644 index 0000000000000..b4cef59a3e2c3 --- /dev/null +++ b/src/Symfony/Component/Cache/Traits/RedisClusterProxy.php @@ -0,0 +1,63 @@ + + * + * 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 + * + * @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); + } +} diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index 4c5d1564bb99c..2bedb5bb73ec8 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -52,7 +52,7 @@ private function init($redisClient, $namespace, $defaultLifetime, ?MarshallerInt 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 @@ protected function doClear($namespace) 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 @@ private function pipeline(\Closure $generator) { $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 diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php index 36adf2424d618..9c08ddcc0128b 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php @@ -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 @@ public function __construct($redis, array $options = array()) !$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))); } diff --git a/src/Symfony/Component/Lock/Store/RedisStore.php b/src/Symfony/Component/Lock/Store/RedisStore.php index 10174b7f54d18..08965dbfb1628 100644 --- a/src/Symfony/Component/Lock/Store/RedisStore.php +++ b/src/Symfony/Component/Lock/Store/RedisStore.php @@ -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 @@ public function exists(Key $key) */ 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); } diff --git a/src/Symfony/Component/Lock/Store/StoreFactory.php b/src/Symfony/Component/Lock/Store/StoreFactory.php index 701bf2b8bbb50..5f97a8715df34 100644 --- a/src/Symfony/Component/Lock/Store/StoreFactory.php +++ b/src/Symfony/Component/Lock/Store/StoreFactory.php @@ -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) { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy