Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8341158

Browse filesBrowse files
bug #47003 [Cache] Ensured that redis adapter can use multiple redis sentinel hosts (warslett)
This PR was squashed before being merged into the 5.4 branch. Discussion ---------- [Cache] Ensured that redis adapter can use multiple redis sentinel hosts This PR ensures that RedisAdapter for Symfony Cache component works as expected when a redis_sentinel argument is provided with multiple redis sentinel hosts. Previously if using the redis php extension and multiple hosts were provided RedisTrait::createConnection would ignore the redis_sentinel parameter and instead return a RedisArray object which would not work because it would be an array of sentinel hosts rather than redis hosts. This PR introduces the correct behaviour where by RedisTrait::createConnection will loop through each of the provided sentinel hosts trying each one to get the address of the mast redis instance. If none of the provided hosts can return the address of a master instance it will throw an exception. I'm not too sure how to test this behaviour. There doesn't appear to be any tests for redis sentinel behaviour in place currently. I have tested manually both with a multi redis sentinel setup and with a single standard redis instance and the code now functions as expected in both scenarios. | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes/no | New feature? | no - bugfix | Deprecations? | no - behaviour as documented and as implemented in 4.4 | Tickets | [#46998](#46998) | License | MIT | Doc PR | none - bugfix Commits ------- 39998d3 [Cache] Ensured that redis adapter can use multiple redis sentinel hosts
2 parents a445682 + 39998d3 commit 8341158
Copy full SHA for 8341158

File tree

Expand file treeCollapse file tree

3 files changed

+22
-14
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+22
-14
lines changed

‎.github/workflows/integration-tests.yml

Copy file name to clipboardExpand all lines: .github/workflows/integration-tests.yml
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ jobs:
171171
env:
172172
REDIS_HOST: 'localhost:16379'
173173
REDIS_CLUSTER_HOSTS: 'localhost:7000 localhost:7001 localhost:7002 localhost:7003 localhost:7004 localhost:7005'
174-
REDIS_SENTINEL_HOSTS: 'localhost:26379'
174+
REDIS_SENTINEL_HOSTS: 'localhost:26379 localhost:26379 localhost:26379'
175175
REDIS_SENTINEL_SERVICE: redis_sentinel
176176
MESSENGER_REDIS_DSN: redis://127.0.0.1:7006/messages
177177
MESSENGER_AMQP_DSN: amqp://localhost/%2f/messages

‎src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterSentinelTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterSentinelTest.php
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ public function testInvalidDSNHasBothClusterAndSentinel()
4747
public function testExceptionMessageWhenFailingToRetrieveMasterInformation()
4848
{
4949
$hosts = getenv('REDIS_SENTINEL_HOSTS');
50-
$firstHost = explode(' ', $hosts)[0];
50+
$dsn = 'redis:?host['.str_replace(' ', ']&host[', $hosts).']';
5151
$this->expectException(\Symfony\Component\Cache\Exception\InvalidArgumentException::class);
52-
$this->expectExceptionMessage('Failed to retrieve master information from master name "invalid-masterset-name" and address "'.$firstHost.'".');
53-
AbstractAdapter::createConnection('redis:?host['.str_replace(' ', ']&host[', $hosts).']', ['redis_sentinel' => 'invalid-masterset-name']);
52+
$this->expectExceptionMessage('Failed to retrieve master information from sentinel "invalid-masterset-name" and dsn "'.$dsn.'".');
53+
AbstractAdapter::createConnection($dsn, ['redis_sentinel' => 'invalid-masterset-name']);
5454
}
5555
}

‎src/Symfony/Component/Cache/Traits/RedisTrait.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Traits/RedisTrait.php
+18-10Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ public static function createConnection(string $dsn, array $options = [])
179179
}
180180

181181
if (null === $params['class'] && \extension_loaded('redis')) {
182-
$class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) ? \RedisArray::class : \Redis::class);
182+
$class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) && !isset($params['redis_sentinel']) ? \RedisArray::class : \Redis::class);
183183
} else {
184184
$class = $params['class'] ?? \Predis\Client::class;
185185

@@ -193,21 +193,29 @@ public static function createConnection(string $dsn, array $options = [])
193193
$redis = new $class();
194194

195195
$initializer = static function ($redis) use ($connect, $params, $dsn, $auth, $hosts, $tls) {
196-
$host = $hosts[0]['host'] ?? $hosts[0]['path'];
197-
$port = $hosts[0]['port'] ?? 0;
196+
$hostIndex = 0;
197+
do {
198+
$host = $hosts[$hostIndex]['host'] ?? $hosts[$hostIndex]['path'];
199+
$port = $hosts[$hostIndex]['port'] ?? 0;
200+
$address = false;
201+
202+
if (isset($hosts[$hostIndex]['host']) && $tls) {
203+
$host = 'tls://'.$host;
204+
}
198205

199-
if (isset($hosts[0]['host']) && $tls) {
200-
$host = 'tls://'.$host;
201-
}
206+
if (!isset($params['redis_sentinel'])) {
207+
break;
208+
}
202209

203-
if (isset($params['redis_sentinel'])) {
204210
$sentinel = new \RedisSentinel($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout']);
205211

206-
if (!$address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) {
207-
throw new InvalidArgumentException(sprintf('Failed to retrieve master information from master name "%s" and address "%s:%d".', $params['redis_sentinel'], $host, $port));
212+
if ($address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) {
213+
[$host, $port] = $address;
208214
}
215+
} while (++$hostIndex < \count($hosts) && !$address);
209216

210-
[$host, $port] = $address;
217+
if (isset($params['redis_sentinel']) && !$address) {
218+
throw new InvalidArgumentException(sprintf('Failed to retrieve master information from sentinel "%s" and dsn "%s".', $params['redis_sentinel'], $dsn));
211219
}
212220

213221
try {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.