8000 [Messenger][Redis] Adding support for lazy connect · symfony/symfony@1d7c801 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1d7c801

Browse files
Nyholmfabpot
authored andcommitted
[Messenger][Redis] Adding support for lazy connect
1 parent 8430954 commit 1d7c801

File tree

4 files changed

+82
-8
lines changed

4 files changed

+82
-8
lines changed

src/Symfony/Component/Messenger/Bridge/Redis/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* Added a `delete_after_reject` option to the DSN to allow control over message
88
deletion, similar to `delete_after_ack`.
9+
* Added option `lazy` to delay connecting to Redis server until we first use it.
910

1011
5.1.0
1112
-----

src/Symfony/Component/Messenger/Bridge/Redis/Tests/Transport/ConnectionTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,4 +387,16 @@ public function testLastErrorGetsCleared()
387387

388388
$this->assertSame('xack error', $e->getMessage());
389389
}
390+
391+
public function testLazy()
392+
{
393+
$redis = new \Redis();
394+
$connection = Connection::fromDsn('redis://localhost/messenger-lazy?lazy=1', [], $redis);
395+
396+
$connection->add('1', []);
397+
$this->assertNotEmpty($message = $connection->get());
398+
$this->assertSame('1', $message['body']);
399+
$connection->reject($message['id']);
400+
$redis->del('messenger-lazy');
401+
}
390402
}

src/Symfony/Component/Messenger/Bridge/Redis/Transport/Connection.php

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class Connection
3939
'tls' => false,
4040
'redeliver_timeout' => 3600, // Timeout before redeliver messages still in pending state (seconds)
4141
'claim_interval' => 60000, // Interval by which pending/abandoned messages should be checked
42+
'lazy' => false,
4243
];
4344

4445
private $connection;
@@ -61,23 +62,42 @@ public function __construct(array $configuration, array $connectionCredentials =
6162
throw new LogicException('The redis transport requires php-redis 4.3.0 or higher.');
6263
}
6364

64-
$this->connection = $redis ?: new \Redis();
65-
$this->connectio 10000 n->connect($connectionCredentials['host'] ?? '127.0.0.1', $connectionCredentials['port'] ?? 6379);
66-
$this->connection->setOption(\Redis::OPT_SERIALIZER, $redisOptions['serializer'] ?? \Redis::SERIALIZER_PHP);
67-
65+
$host = $connectionCredentials['host'] ?? '127.0.0.1';
66+
$port = $connectionCredentials['port'] ?? 6379;
67+
$serializer = $redisOptions['serializer'] ?? \Redis::SERIALIZER_PHP;
68+
$dbIndex = $configuration['dbindex'] ?? self::DEFAULT_OPTIONS['dbindex'];
6869
$auth = $connectionCredentials['auth'] ?? null;
6970
if ('' === $auth) {
7071
$auth = null;
7172
}
7273

73-
if (null !== $auth && !$this->connection->auth($auth)) {
74-
throw new InvalidArgumentException('Redis connection failed: '.$this->connection->getLastError());
74+
$initializer = static function ($redis) use ($host, $port, $auth, $serializer, $dbIndex) {
75+
$redis->connect($host, $port);
76+
$redis->setOption(\Redis::OPT_SERIALIZER, $serializer);
77+
78+
if (null !== $auth && !$redis->auth($auth)) {
79+
throw new InvalidArgumentException('Redis connection failed: '.$redis->getLastError());
80+
}
81+
82+
if ($dbIndex && !$redis->select($dbIndex)) {
83+
throw new InvalidArgumentException('Redis connection failed: '.$redis->getLastError());
84+
}
85+
86+
return true;
87+
};
88+
89+
if (null === $redis) {
90+
$redis = new \Redis();
7591
}
7692

77-
if (($dbIndex = $configuration['dbindex'] ?? self::DEFAULT_OPTIONS['dbindex']) && !$this->connection->select($dbIndex)) {
78-
throw new InvalidArgumentException('Redis connection failed: '.$this->connection->getLastError());
93+
if ($configuration['lazy'] ?? self::DEFAULT_OPTIONS['lazy']) {
94+
$redis = new RedisProxy($redis, $initializer);
95+
} else {
96+
$initializer($redis);
7997
}
8098

99+
$this->connection = $redis;
100+
81101
foreach (['stream', 'group', 'consumer'] as $key) {
82102
if (isset($configuration[$key]) && '' === $configuration[$key]) {
83103
throw new InvalidArgumentException(sprintf('"%s" should be configured, got an empty string.', $key));
@@ -165,6 +185,7 @@ public static function fromDsn(string $dsn, array $redisOptions = [], \Redis $re
165185
'stream' => $redisOptions['stream'] ?? null,
166186
'group' => $redisOptions['group'] ?? null,
167187
'consumer' => $redisOptions['consumer'] ?? null,
188+
'lazy' => $redisOptions['lazy'] ?? self::DEFAULT_OPTIONS['lazy'],
168189
'auto_setup' => $autoSetup,
169190
'stream_max_entries' => $maxEntries,
170191
'delete_after_ack' => $deleteAfterAck,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Bridge\Redis\Transport;
13+
14+
/**
15+
* Allow to delay connection to Redis.
16+
*
17+
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
18+
* @author Nicolas Grekas <p@tchwork.com>
19+
*
20+
* @internal
21+
*/
22+
class RedisProxy
23+
{
24+
private $redis;
25+
private $initializer;
26+
private $ready = false;
27+
28+
public function __construct(\Redis $redis, \Closure $initializer)
29+
{
30+
$this->redis = $redis;
31+
$this->initializer = $initializer;
32+
}
33+
34+
public function __call(string $method, array $args)
35+
{
36+
$this->ready ?: $this->ready = $this->initializer->__invoke($this->redis);
37+
38+
return $this->redis->{$method}(...$args);
39+
}
40+
}

0 commit comments

Comments
 (0)
0