Skip to content

Commit 2153d49

Browse files
Add support for valkey: / valkeys: schemes
1 parent b28e597 commit 2153d49

File tree

18 files changed

+75
-37
lines changed

18 files changed

+75
-37
lines changed

src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ protected function loadCacheDriver(string $cacheName, string $objectManagerName,
301301
$cacheDef->addMethodCall('setMemcached', [new Reference($this->getObjectManagerElementName(\sprintf('%s_memcached_instance', $objectManagerName)))]);
302302
break;
303303
case 'redis':
304+
case 'valkey':
304305
$redisClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.redis.class').'%';
305306
$redisInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.redis_instance.class').'%';
306307
$redisHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.redis_host').'%';

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBe
12841284
->scalarNode('directory')->defaultValue('%kernel.cache_dir%/pools/app')->end()
12851285
->scalarNode('default_psr6_provider')->end()
12861286
->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end()
1287+
->scalarNode('default_valkey_provider')->defaultValue('valkey://localhost')->end()
12871288
->scalarNode('default_memcached_provider')->defaultValue('memcached://localhost')->end()
12881289
->scalarNode('default_doctrine_dbal_provider')->defaultValue('database_connection')->end()
12891290
->scalarNode('default_pdo_provider')->defaultValue($willBeAvailable('doctrine/dbal', Connection::class) && class_exists(DoctrineAdapter::class) ? 'database_connection' : null)->end()

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,7 +2497,7 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con
24972497
// Inline any env vars referenced in the parameter
24982498
$container->setParameter('cache.prefix.seed', $container->resolveEnvPlaceholders($container->getParameter('cache.prefix.seed'), true));
24992499
}
2500-
foreach (['psr6', 'redis', 'memcached', 'doctrine_dbal', 'pdo'] as $name) {
2500+
foreach (['psr6', 'redis', 'valkey', 'memcached', 'doctrine_dbal', 'pdo'] as $name) {
25012501
if (isset($config[$name = 'default_'.$name.'_provider'])) {
25022502
$container->setAlias('cache.'.$name, new Alias(CachePoolPass::getServiceProvider($container, $config[$name]), false));
25032503
}
@@ -2509,12 +2509,13 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con
25092509
'tags' => false,
25102510
];
25112511
}
2512+
$redisTawAwareAdapters = [['cache.adapter.redis_tag_aware'], ['cache.adapter.valkey_tag_aware']];
25122513
foreach ($config['pools'] as $name => $pool) {
25132514
$pool['adapters'] = $pool['adapters'] ?: ['cache.app'];
25142515

2515-
$isRedisTagAware = ['cache.adapter.redis_tag_aware'] === $pool['adapters'];
2516+
$isRedisTagAware = \in_array($pool['adapters'], $redisTawAwareAdapters, true);
25162517
foreach ($pool['adapters'] as $provider => $adapter) {
2517-
if (($config['pools'][$adapter]['adapters'] ?? null) === ['cache.adapter.redis_tag_aware']) {
2518+
if (\in_array($config['pools'][$adapter]['adapters'] ?? null, $redisTawAwareAdapters, true)) {
25182519
$isRedisTagAware = true;
25192520
} elseif ($config['pools'][$adapter]['tags'] ?? false) {
25202521
$pool['adapters'][$provider] = $adapter = '.'.$adapter.'.inner';

src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
'reset' => 'reset',
141141
])
142142
->tag('monolog.logger', ['channel' => 'cache'])
143+
->alias('cache.adapter.valkey', 'cache.adapter.redis')
143144

144145
->set('cache.adapter.redis_tag_aware', RedisTagAwareAdapter::class)
145146
->abstract()
@@ -156,6 +157,7 @@
156157
'reset' => 'reset',
157158
])
158159
->tag('monolog.logger', ['channel' => 'cache'])
160+
->alias('cache.adapter.valkey_tag_aware', 'cache.adapter.redis_tag_aware')
159161

160162
->set('cache.adapter.memcached', MemcachedAdapter::class)
161163
->abstract()

src/Symfony/Component/Cache/Adapter/AbstractAdapter.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public static function createSystemCache(string $namespace, int $defaultLifetime
111111

112112
public static function createConnection(#[\SensitiveParameter] string $dsn, array $options = []): mixed
113113
{
114-
if (str_starts_with($dsn, 'redis:') || str_starts_with($dsn, 'rediss:')) {
114+
if (str_starts_with($dsn, 'redis:') || str_starts_with($dsn, 'rediss:') || str_starts_with($dsn, 'valkey:') || str_starts_with($dsn, 'valkeys:')) {
115115
return RedisAdapter::createConnection($dsn, $options);
116116
}
117117
if (str_starts_with($dsn, 'memcached:')) {
@@ -128,7 +128,7 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
128128
return PdoAdapter::createConnection($dsn, $options);
129129
}
130130

131-
throw new InvalidArgumentException('Unsupported DSN: it does not start with "redis[s]:", "memcached:", "couchbase:", "mysql:", "oci:", "pgsql:", "sqlsrv:" nor "sqlite:".');
131+
throw new InvalidArgumentException('Unsupported DSN: it does not start with "redis[s]:", "valkey[s]:", "memcached:", "couchbase:", "mysql:", "oci:", "pgsql:", "sqlsrv:" nor "sqlite:".');
132132
}
133133

134134
public function commit(): bool

src/Symfony/Component/Cache/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Add support for `valkey:` / `valkeys:` schemes
8+
49
7.2
510
---
611

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

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ trait RedisTrait
4444
'retry_interval' => 0,
4545
'tcp_keepalive' => 0,
4646
'lazy' => null,
47-
'redis_cluster' => false,
48-
'redis_sentinel' => null,
47+
'cluster' => false,
48+
'sentinel_master' => null,
4949
'dbindex' => 0,
5050
'failover' => 'none',
5151
'ssl' => null, // see https://php.net/context.ssl
@@ -87,13 +87,13 @@ private function init(\Redis|Relay|\RedisArray|\RedisCluster|\Predis\ClientInter
8787
*/
8888
public static function createConnection(#[\SensitiveParameter] string $dsn, array $options = []): \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|Relay
8989
{
90-
if (str_starts_with($dsn, 'redis:')) {
91-
$scheme = 'redis';
92-
} elseif (str_starts_with($dsn, 'rediss:')) {
93-
$scheme = 'rediss';
94-
} else {
95-
throw new InvalidArgumentException('Invalid Redis DSN: it does not start with "redis[s]:".');
96-
}
90+
$scheme = match (true) {
91+
str_starts_with($dsn, 'redis:') => 'redis:',
92+
str_starts_with($dsn, 'rediss:') => 'rediss:',
93+
str_starts_with($dsn, 'valkey:') => 'valkey:',
94+
str_starts_with($dsn, 'valkeys:') => 'valkeys:',
95+
default => throw new InvalidArgumentException('Invalid Redis DSN: it does not start with "redis[s]:" nor "valkey[s]:".'),
96+
};
9797

9898
if (!\extension_loaded('redis') && !class_exists(\Predis\Client::class)) {
9999
throw new CacheException('Cannot find the "redis" extension nor the "predis/predis" package.');
@@ -121,7 +121,7 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
121121

122122
$query = $hosts = [];
123123

124-
$tls = 'rediss' === $scheme;
124+
$tls = 'rediss' === $scheme || 'valkeys' === $scheme;
125125
$tcpScheme = $tls ? 'tls' : 'tcp';
126126

127127
if (isset($params['query'])) {
@@ -178,24 +178,24 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
178178
throw new InvalidArgumentException('Cannot use both "redis_sentinel" and "sentinel_master" at the same time.');
179179
}
180180

181-
$params['redis_sentinel'] ??= $params['sentinel_master'] ?? null;
181+
$params['sentinel_master'] ??= $params['redis_sentinel'] ?? null;
182182

183-
if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class) && !class_exists(\RedisSentinel::class) && !class_exists(Sentinel::class)) {
183+
if (isset($params['sentinel_master']) && !class_exists(\Predis\Client::class) && !class_exists(\RedisSentinel::class) && !class_exists(Sentinel::class)) {
184184
throw new CacheException('Redis Sentinel support requires one of: "predis/predis", "ext-redis >= 5.2", "ext-relay".');
185185
}
186186

187187
if (isset($params['lazy'])) {
188188
$params['lazy'] = filter_var($params['lazy'], \FILTER_VALIDATE_BOOLEAN);
189189
}
190-
$params['redis_cluster'] = filter_var($params['redis_cluster'], \FILTER_VALIDATE_BOOLEAN);
190+
$params['cluster'] = filter_var($params['cluster'], \FILTER_VALIDATE_BOOLEAN) || filter_var($params['redis_cluster'], \FILTER_VALIDATE_BOOLEAN);
191191

192-
if ($params['redis_cluster'] && isset($params['redis_sentinel'])) {
193-
throw new InvalidArgumentException('Cannot use both "redis_cluster" and "redis_sentinel" at the same time.');
192+
if ($params['cluster'] && isset($params['sentinel_master'])) {
193+
throw new InvalidArgumentException('Cannot use both "cluster" and "sentinel" at the same time.');
194194
}
195195

196196
$class = $params['class'] ?? match (true) {
197-
$params['redis_cluster'] => \extension_loaded('redis') ? \RedisCluster::class : \Predis\Client::class,
198-
isset($params['redis_sentinel']) => match (true) {
197+
$params['cluster'] => \extension_loaded('redis') ? \RedisCluster::class : \Predis\Client::class,
198+
isset($params['sentinel_master']) => match (true) {
199199
\extension_loaded('redis') => \Redis::class,
200200
\extension_loaded('relay') => Relay::class,
201201
default => \Predis\Client::class,
@@ -206,7 +206,7 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
206206
default => \Predis\Client::class,
207207
};
208208

209-
if (isset($params['redis_sentinel']) && !is_a($class, \Predis\Client::class, true) && !class_exists(\RedisSentinel::class) && !class_exists(Sentinel::class)) {
209+
if (isset($params['sentinel_master']) && !is_a($class, \Predis\Client::class, true) && !class_exists(\RedisSentinel::class) && !class_exists(Sentinel::class)) {
210210
throw new CacheException(\sprintf('Cannot use Redis Sentinel: class "%s" does not extend "Predis\Client" and neither ext-redis >= 5.2 nor ext-relay have been found.', $class));
211211
}
212212

@@ -230,7 +230,7 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
230230
$host = 'tls://'.$host;
231231
}
232232

233-
if (!isset($params['redis_sentinel'])) {
233+
if (!isset($params['sentinel_master'])) {
234234
break;
235235
}
236236

@@ -256,15 +256,15 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
256256
$sentinel = @new $sentinelClass($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...$extra);
257257
}
258258

259-
if ($address = @$sentinel->getMasterAddrByName($params['redis_sentinel'])) {
259+
if ($address = @$sentinel->getMasterAddrByName($params['sentinel_master'])) {
260260
[$host, $port] = $address;
261261
}
262262
} catch (\RedisException|\Relay\Exception $redisException) {
263263
}
264264
} while (++$hostIndex < \count($hosts) && !$address);
265265

266-
if (isset($params['redis_sentinel']) && !$address) {
267-
throw new InvalidArgumentException(\sprintf('Failed to retrieve master information from sentinel "%s".', $params['redis_sentinel']), previous: $redisException ?? null);
266+
if (isset($params['sentinel_master']) && !$address) {
267+
throw new InvalidArgumentException(\sprintf('Failed to retrieve master information from sentinel "%s".', $params['sentinel_master']), previous: $redisException ?? null);
268268
}
269269

270270
try {
@@ -379,11 +379,11 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
379379

380380
$redis = $params['lazy'] ? RedisClusterProxy::createLazyProxy($initializer) : $initializer();
381381
} elseif (is_a($class, \Predis\ClientInterface::class, true)) {
382-
if ($params['redis_cluster']) {
382+
if ($params['cluster']) {
383383
$params['cluster'] = 'redis';
384-
} elseif (isset($params['redis_sentinel'])) {
384+
} elseif (isset($params['sentinel_master'])) {
385385
$params['replication'] = 'sentinel';
386-
$params['service'] = $params['redis_sentinel'];
386+
$params['service'] = $params['sentinel_master'];
387387
}
388388
$params += ['parameters' => []];
389389
$params['parameters'] += [
@@ -411,7 +411,7 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
411411
}
412412
}
413413

414-
if (1 === \count($hosts) && !($params['redis_cluster'] || $params['redis_sentinel'])) {
414+
if (1 === \count($hosts) && !($params['cluster'] || $params['sentinel_master'])) {
415415
$hosts = $hosts[0];
416416
} elseif (\in_array($params['failover'], ['slaves', 'distribute'], true) && !isset($params['replication'])) {
417417
$params['replication'] = true;
@@ -420,7 +420,7 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
420420
$params['exceptions'] = false;
421421

422422
$redis = new $class($hosts, array_diff_key($params, self::$defaultConnectionOptions));
423-
if (isset($params['redis_sentinel'])) {
423+
if (isset($params['sentinel_master'])) {
424424
$redis->getConnection()->setSentinelTimeout($params['timeout']);
425425
}
426426
} elseif (class_exists($class, false)) {

src/Symfony/Component/HttpFoundation/CHANGELOG.md

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

77
* Add support for iterable of string in `StreamedResponse`
88
* Add `EventStreamResponse` and `ServerEvent` classes to streamline server event streaming
9+
* Add support for `valkey:` / `valkeys:` schemes for sessions
910

1011
7.2
1112
---

src/Symfony/Component/HttpFoundation/Session/Storage/Handler/SessionHandlerFactory.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ public static function createHandler(object|string $connection, array $options =
5757

5858
case str_starts_with($connection, 'redis:'):
5959
case str_starts_with($connection, 'rediss:'):
60+
case str_starts_with($connection, 'valkey:'):
61+
case str_starts_with($connection, 'valkeys:'):
6062
case str_starts_with($connection, 'memcached:'):
6163
if (!class_exists(AbstractAdapter::class)) {
6264
throw new \InvalidArgumentException('Unsupported Redis or Memcached DSN. Try running "composer require symfony/cache".');

src/Symfony/Component/Lock/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Add support for `valkey:` / `valkeys:` schemes
8+
49
7.2
510
---
611

src/Symfony/Component/Lock/Store/StoreFactory.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ public static function createStore(#[\SensitiveParameter] object|string $connect
6262

6363
case str_starts_with($connection, 'redis:'):
6464
case str_starts_with($connection, 'rediss:'):
65+
case str_starts_with($connection, 'valkey:'):
66+
case str_starts_with($connection, 'valkeys:'):
6567
case str_starts_with($connection, 'memcached:'):
6668
if (!class_exists(AbstractAdapter::class)) {
6769
throw new InvalidArgumentException('Unsupported Redis or Memcached DSN. Try running "composer require symfony/cache".');

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

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

77
* Implement the `KeepaliveReceiverInterface` to enable asynchronously notifying Redis that the job is still being processed, in order to avoid timeouts
8+
* Add support for `valkey:` / `valkeys:` schemes
89

910
6.3
1011
---

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public function testSupportsOnlyRedisTransports()
2828

2929
$this->assertTrue($factory->supports('redis://localhost', []));
3030
$this->assertTrue($factory->supports('rediss://localhost', []));
31+
$this->assertTrue($factory->supports('valkey://localhost', []));
32+
$this->assertTrue($factory->supports('valkeys://localhost', []));
3133
$this->assertTrue($factory->supports('redis:?host[host1:5000]&host[host2:5000]&host[host3:5000]&sentinel_master=test&dbindex=0', []));
3234
$this->assertFalse($factory->supports('sqs://localhost', []));
3335
$this->assertFalse($factory->supports('invalid-dsn', []));

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public static function fromDsn(#[\SensitiveParameter] string $dsn, array $option
238238
if (!str_contains($dsn, ',')) {
239239
$params = self::parseDsn($dsn, $options);
240240

241-
if (isset($params['host']) && 'rediss' === $params['scheme']) {
241+
if (isset($params['host']) && ('rediss' === $params['scheme'] || 'valkeys' === $params['scheme'])) {
242242
$params['host'] = 'tls://'.$params['host'];
243243
}
244244
} else {
@@ -249,7 +249,7 @@ public static function fromDsn(#[\SensitiveParameter] string $dsn, array $option
249249

250250
// Merge all the URLs, the last one overrides the previous ones
251251
$params = array_merge(...$paramss);
252-
$tls = 'rediss' === $params['scheme'];
252+
$tls = 'rediss' === $params['scheme'] || 'valkeys' === $params['scheme'];
253253

254254
// Regroup all the hosts in an array interpretable by RedisCluster
255255
$params['host'] = array_map(function ($params) use ($tls) {
@@ -284,7 +284,7 @@ public static function fromDsn(#[\SensitiveParameter] string $dsn, array $option
284284
parse_str($params['query'], $query);
285285

286286
if (isset($query['host'])) {
287-
$tls = 'rediss' === $params['scheme'];
287+
$tls = 'rediss' === $params['scheme'] || 'valkeys' === $params['scheme'];
288288
$tcpScheme = $tls ? 'tls' : 'tcp';
289289

290290
if (!\is_array($hosts = $query['host'])) {
@@ -325,7 +325,13 @@ public static function fromDsn(#[\SensitiveParameter] string $dsn, array $option
325325
private static function parseDsn(string $dsn, array &$options): array
326326
{
327327
$url = $dsn;
328-
$scheme = str_starts_with($dsn, 'rediss:') ? 'rediss' : 'redis';
328+
$scheme = match (true) {
329+
str_starts_with($dsn, 'redis:') => 'redis:',
330+
str_starts_with($dsn, 'rediss:') => 'rediss:',
331+
str_starts_with($dsn, 'valkey:') => 'valkey:',
332+
str_starts_with($dsn, 'valkeys:') => 'valkeys:',
333+
default => throw new InvalidArgumentException('Invalid Redis DSN: it does not start with "redis[s]:" nor "valkey[s]:".'),
334+
};
329335

330336
if (preg_match('#^'.$scheme.':///([^:@])+$#', $dsn)) {
331337
$url = str_replace($scheme.':', 'file:', $dsn);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ public function createTransport(#[\SensitiveParameter] string $dsn, array $optio
3232

3333
public function supports(#[\SensitiveParameter] string $dsn, array $options): bool
3434
{
35-
return str_starts_with($dsn, 'redis:') || str_starts_with($dsn, 'rediss:');
35+
return str_starts_with($dsn, 'redis:') || str_starts_with($dsn, 'rediss:') || str_starts_with($dsn, 'valkey:') || str_starts_with($dsn, 'valkeys:');
3636
}
3737
}

src/Symfony/Component/Messenger/Transport/TransportFactory.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public function createTransport(#[\SensitiveParameter] string $dsn, array $optio
4545
$packageSuggestion = ' Run "composer require symfony/doctrine-messenger" to install Doctrine transport.';
4646
} elseif (str_starts_with($dsn, 'redis://') || str_starts_with($dsn, 'rediss://')) {
4747
$packageSuggestion = ' Run "composer require symfony/redis-messenger" to install Redis transport.';
48+
} elseif (str_starts_with($dsn, 'valkey://') || str_starts_with($dsn, 'valkeys://')) {
49+
$packageSuggestion = ' Run "composer require symfony/redis-messenger" to install Valkey transport.';
4850
} elseif (str_starts_with($dsn, 'sqs://') || preg_match('#^https://sqs\.[\w\-]+\.amazonaws\.com/.+#', $dsn)) {
4951
$packageSuggestion = ' Run "composer require symfony/amazon-sqs-messenger" to install Amazon SQS transport.';
5052
} elseif (str_starts_with($dsn, 'beanstalkd://')) {

src/Symfony/Component/Semaphore/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Add support for `valkey:` / `valkeys:` schemes
8+
49
6.3
510
---
611

0 commit comments

Comments
 (0)