Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit2153d49

Browse files
Add support forvalkey: /valkeys: schemes
1 parentb28e597 commit2153d49

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', [newReference($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,newAlias(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
publicstaticfunctioncreateConnection(#[\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-
thrownewInvalidArgumentException('Unsupported DSN: it does not start with "redis[s]:", "memcached:", "couchbase:", "mysql:", "oci:", "pgsql:", "sqlsrv:" nor "sqlite:".');
131+
thrownewInvalidArgumentException('Unsupported DSN: it does not start with "redis[s]:", "valkey[s]:", "memcached:", "couchbase:", "mysql:", "oci:", "pgsql:", "sqlsrv:" nor "sqlite:".');
132132
}
133133

134134
publicfunctioncommit():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
publicstaticfunctioncreateConnection(#[\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-
thrownewInvalidArgumentException('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 =>thrownewInvalidArgumentException('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
thrownewCacheException('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
thrownewInvalidArgumentException('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
thrownewCacheException('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-
thrownewInvalidArgumentException('Cannot use both "redis_cluster" and "redis_sentinel" at the same time.');
192+
if ($params['cluster'] &&isset($params['sentinel_master'])) {
193+
thrownewInvalidArgumentException('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
thrownewCacheException(\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-
thrownewInvalidArgumentException(\sprintf('Failed to retrieve master information from sentinel "%s".',$params['redis_sentinel']), previous:$redisException ??null);
266+
if (isset($params['sentinel_master']) && !$address) {
267+
thrownewInvalidArgumentException(\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
casestr_starts_with($connection,'redis:'):
5959
casestr_starts_with($connection,'rediss:'):
60+
casestr_starts_with($connection,'valkey:'):
61+
casestr_starts_with($connection,'valkeys:'):
6062
casestr_starts_with($connection,'memcached:'):
6163
if (!class_exists(AbstractAdapter::class)) {
6264
thrownew \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
casestr_starts_with($connection,'redis:'):
6464
casestr_starts_with($connection,'rediss:'):
65+
casestr_starts_with($connection,'valkey:'):
66+
casestr_starts_with($connection,'valkeys:'):
6567
casestr_starts_with($connection,'memcached:'):
6668
if (!class_exists(AbstractAdapter::class)) {
6769
thrownewInvalidArgumentException('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
privatestaticfunctionparseDsn(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 =>thrownewInvalidArgumentException('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
publicfunctionsupports(#[\SensitiveParameter]string$dsn,array$options):bool
3434
{
35-
returnstr_starts_with($dsn,'redis:') ||str_starts_with($dsn,'rediss:');
35+
returnstr_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)

[8]ページ先頭

©2009-2025 Movatter.jp