diff --git a/src/Symfony/Component/Cache/CHANGELOG.md b/src/Symfony/Component/Cache/CHANGELOG.md index 73965c2058903..2b6c4b177cee9 100644 --- a/src/Symfony/Component/Cache/CHANGELOG.md +++ b/src/Symfony/Component/Cache/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +5.3.0 +----- + +* added support for connecting to Redis Sentinel clusters when using the Redis PHP extension + 5.2.0 ----- diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PredisAdapterSentinelTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PredisAdapterSentinelTest.php new file mode 100644 index 0000000000000..e6de9b3ee6bbe --- /dev/null +++ b/src/Symfony/Component/Cache/Tests/Adapter/PredisAdapterSentinelTest.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Tests\Adapter; + +use Symfony\Component\Cache\Adapter\AbstractAdapter; + +/** + * @group integration + */ +class PredisAdapterSentinelTest extends AbstractRedisAdapterTest +{ + public static function setUpBeforeClass(): void + { + if (!class_exists(\Predis\Client::class)) { + self::markTestSkipped('The Predis\Client class is required.'); + } + if (!$hosts = getenv('REDIS_SENTINEL_HOSTS')) { + self::markTestSkipped('REDIS_SENTINEL_HOSTS env var is not defined.'); + } + if (!$service = getenv('REDIS_SENTINEL_SERVICE')) { + self::markTestSkipped('REDIS_SENTINEL_SERVICE env var is not defined.'); + } + + self::$redis = AbstractAdapter::createConnection('redis:?host['.str_replace(' ', ']&host[', $hosts).']', ['redis_sentinel' => $service, 'class' => \Predis\Client::class]); + } +} diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterSentinelTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterSentinelTest.php index 82b9f08b65474..84ea7969ad962 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterSentinelTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterSentinelTest.php @@ -21,8 +21,8 @@ class RedisAdapterSentinelTest extends AbstractRedisAdapterTest { public static function setUpBeforeClass(): void { - if (!class_exists('Predis\Client')) { - self::markTestSkipped('The Predis\Client class is required.'); + if (!class_exists(\RedisSentinel::class)) { + self::markTestSkipped('The RedisSentinel class is required.'); } if (!$hosts = getenv('REDIS_SENTINEL_HOSTS')) { self::markTestSkipped('REDIS_SENTINEL_HOSTS env var is not defined.'); diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index 317879aa494e2..6e6b6d0e4f6c6 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -159,13 +159,17 @@ public static function createConnection($dsn, array $options = []) throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); } - if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class)) { - throw new CacheException(sprintf('Redis Sentinel support requires the "predis/predis" package: "%s".', $dsn)); + $params += $query + $options + self::$defaultConnectionOptions; + + if (isset($params['redis_sentinel']) && (!class_exists(\Predis\Client::class) || !class_exists(\RedisSentinel::class))) { + throw new CacheException(sprintf('Redis Sentinel support requires the "predis/predis" package or the "redis" extension v5.2 or higher: "%s".', $dsn)); } - $params += $query + $options + self::$defaultConnectionOptions; + if ($params['redis_cluster'] && isset($params['redis_sentinel'])) { + throw new InvalidArgumentException(sprintf('Cannot use both "redis_cluster" and "redis_sentinel" at the same time: "%s".', $dsn)); + } - if (null === $params['class'] && !isset($params['redis_sentinel']) && \extension_loaded('redis')) { + if (null === $params['class'] && \extension_loaded('redis')) { $class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) ? \RedisArray::class : \Redis::class); } else { $class = null === $params['class'] ? \Predis\Client::class : $params['class']; @@ -176,8 +180,19 @@ public static function createConnection($dsn, array $options = []) $redis = new $class(); $initializer = static function ($redis) use ($connect, $params, $dsn, $auth, $hosts) { + $host = $hosts[0]['host'] ?? $hosts[0]['path']; + $port = $hosts[0]['port'] ?? null; + + if (isset($params['redis_sentinel'])) { + $sentinel = new \RedisSentinel($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval']); + + if (![$host, $port] = $sentinel->getMasterAddrByName($params['redis_sentinel'])) { + throw new InvalidArgumentException(sprintf('Failed to retrieve master information from master name "%s" and address "%s:%d".', $params['redis_sentinel'], $host, $port)); + } + } + try { - @$redis->{$connect}($hosts[0]['host'] ?? $hosts[0]['path'], $hosts[0]['port'] ?? null, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval']); + @$redis->{$connect}($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval']); set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); $isConnected = $redis->isConnected(); @@ -254,9 +269,6 @@ public static function createConnection($dsn, array $options = []) } elseif (is_a($class, \Predis\ClientInterface::class, true)) { if ($params['redis_cluster']) { $params['cluster'] = 'redis'; - if (isset($params['redis_sentinel'])) { - throw new InvalidArgumentException(sprintf('Cannot use both "redis_cluster" and "redis_sentinel" at the same time: "%s".', $dsn)); - } } elseif (isset($params['redis_sentinel'])) { $params['replication'] = 'sentinel'; $params['service'] = $params['redis_sentinel']; 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