Description
Symfony version(s) affected: 4.4.x-dev [660b7b4bb4ae391ef2c61d73d258c8ef3c563b66]
Description
In a Redis Sentinel setup, if only a single Redis Sentinel is specified (as we're currently doing in a test environment), then the call to setSentinelTimeout
in RedisTrait.php
throws the exception:
Call to undefined method Predis\Connection\StreamConnection::setSentinelTimeout()
Looking briefly through the code, it appears that if only a single host has been specified, it never initialises properly as a SentinelReplication
interface, instead defaulting as a StreamConnection
. The setSentinelTimeout
method isn't present, and so it throws an exception trying to call it.
How to reproduce
// WORKING: Two different hosts
$redisSentinels = ['192.168.0.1:26379', '192.168.0.2:26379'];
// NOT WORKING: Single host, or the same host multiple times. i.e. You can't "trick" it.
$redisSentinels = ['192.168.0.1:26379'];
$redisSentinels = ['192.168.0.1:26379', '192.168.0.1:26379'];
$redisAuthPassword = 'mypass';
$dsnHostsString = sprintf('?host[%s]', implode(']&host[', $redisSentinels));
$redisDsnString = sprintf('redis:%s@%s', $redisAuthPassword, $dsnHostsString);
$redisOptions = array(
'compression' => true,
'redis_sentinel' => 'name-of-redis-service'
);
$redisClient = RedisAdapter::createConnection($redisDsnString, $redisOptions);
Possible Solution
In RedisTrait.php, line 274, change:
if (1 === \count($hosts) && !$params['redis_cluster']) {
to
if (1 === \count($hosts) && !($params['redis_cluster'] || $params['redis_sentinel'])) {
This will prevent the line below from turning the list of host configs into a single host config when the 'redis_sentinel' parameter is present, and sets up the Connection class properly, preventing the error.
Additional context
Again, this is an unusual bug, in that when using Redis Sentinel you should generally have more than one Sentinel available, but it does cause issues in test platform infrastructure where this may not be the case.