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

Commit81a8ceb

Browse files
[Cache] Enable namespace-based invalidation by prefixing keys with backend-native namespace separators
1 parent86c8a8a commit81a8ceb

25 files changed

+357
-62
lines changed

‎composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"psr/http-message":"^1.0|^2.0",
4848
"psr/link":"^1.1|^2.0",
4949
"psr/log":"^1|^2|^3",
50-
"symfony/contracts":"^3.5",
50+
"symfony/contracts":"^3.6",
5151
"symfony/polyfill-ctype":"~1.8",
5252
"symfony/polyfill-intl-grapheme":"~1.0",
5353
"symfony/polyfill-intl-icu":"~1.0",
@@ -218,7 +218,7 @@
218218
"url":"src/Symfony/Contracts",
219219
"options": {
220220
"versions": {
221-
"symfony/contracts":"3.5.x-dev"
221+
"symfony/contracts":"3.6.x-dev"
222222
}
223223
}
224224
},

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
useSymfony\Component\Yaml\Yaml;
209209
useSymfony\Contracts\Cache\CacheInterface;
210210
useSymfony\Contracts\Cache\CallbackInterface;
211+
useSymfony\Contracts\Cache\NamespacedPoolInterface;
211212
useSymfony\Contracts\Cache\TagAwareCacheInterface;
212213
useSymfony\Contracts\EventDispatcher\EventDispatcherInterface;
213214
useSymfony\Contracts\HttpClient\HttpClientInterface;
@@ -2576,6 +2577,10 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con
25762577
$container->registerAliasForArgument($tagAwareId, TagAwareCacheInterface::class,$pool['name'] ??$name);
25772578
$container->registerAliasForArgument($name, CacheInterface::class,$pool['name'] ??$name);
25782579
$container->registerAliasForArgument($name, CacheItemPoolInterface::class,$pool['name'] ??$name);
2580+
2581+
if (interface_exists(NamespacedPoolInterface::class)) {
2582+
$container->registerAliasForArgument($name, NamespacedPoolInterface::class,$pool['name'] ??$name);
2583+
}
25792584
}
25802585

25812586
$definition->setPublic($pool['public']);

‎src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/cache.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
<tr>
9494
<tdclass="font-normal text-small text-muted nowrap">{{loop.index }}</td>
9595
<tdclass="nowrap">{{'%0.2f'|format((call.end -call.start)*1000) }} ms</td>
96-
<tdclass="nowrap">{{call.name }}()</td>
96+
<tdclass="nowrap">{{call.name }}({{call.namespace|default('') }})</td>
9797
<td>{{ profiler_dump(call.value.result, maxDepth=2) }}</td>
9898
</tr>
9999
{%endfor %}

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
useSymfony\Component\Cache\Traits\AbstractAdapterTrait;
2020
useSymfony\Component\Cache\Traits\ContractsTrait;
2121
useSymfony\Contracts\Cache\CacheInterface;
22+
useSymfony\Contracts\Cache\NamespacedPoolInterface;
2223

2324
/**
2425
* @author Nicolas Grekas <p@tchwork.com>
2526
*/
26-
abstractclass AbstractAdapterimplements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
27+
abstractclass AbstractAdapterimplements AdapterInterface, CacheInterface,NamespacedPoolInterface,LoggerAwareInterface, ResettableInterface
2728
{
2829
use AbstractAdapterTrait;
2930
use ContractsTrait;
@@ -37,7 +38,19 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
3738

3839
protectedfunction__construct(string$namespace ='',int$defaultLifetime =0)
3940
{
40-
$this->namespace ='' ===$namespace ?'' : CacheItem::validateKey($namespace).static::NS_SEPARATOR;
41+
if ('' !==$namespace) {
42+
if (str_contains($namespace,static::NS_SEPARATOR)) {
43+
if (str_contains($namespace,static::NS_SEPARATOR.static::NS_SEPARATOR)) {
44+
thrownewInvalidArgumentException(\sprintf('Cache namespace "%s" contains empty sub-namespace.',$namespace));
45+
}
46+
CacheItem::validateKey(str_replace(static::NS_SEPARATOR,'',$namespace));
47+
}else {
48+
CacheItem::validateKey($namespace);
49+
}
50+
$this->namespace =$namespace.static::NS_SEPARATOR;
51+
}
52+
$this->rootNamespace =$this->namespace;
53+
4154
$this->defaultLifetime =$defaultLifetime;
4255
if (null !==$this->maxIdLength &&\strlen($namespace) >$this->maxIdLength -24) {
4356
thrownewInvalidArgumentException(\sprintf('Namespace must be %d chars max, %d given ("%s").',$this->maxIdLength -24,\strlen($namespace),$namespace));
@@ -118,7 +131,7 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
118131
return MemcachedAdapter::createConnection($dsn,$options);
119132
}
120133
if (str_starts_with($dsn,'couchbase:')) {
121-
if (class_exists('CouchbaseBucket') && CouchbaseBucketAdapter::isSupported()) {
134+
if (class_exists(\CouchbaseBucket::class) && CouchbaseBucketAdapter::isSupported()) {
122135
return CouchbaseBucketAdapter::createConnection($dsn,$options);
123136
}
124137

@@ -159,7 +172,7 @@ public function commit(): bool
159172
$v =$values[$id];
160173
$type =get_debug_type($v);
161174
$message =\sprintf('Failed to save key "{key}" of type %s%s',$type,$einstanceof \Exception ?':'.$e->getMessage() :'.');
162-
CacheItem::log($this->logger,$message, ['key' =>substr($id,\strlen($this->namespace)),'exception' =>$einstanceof \Exception ?$e :null,'cache-adapter' =>get_debug_type($this)]);
175+
CacheItem::log($this->logger,$message, ['key' =>substr($id,\strlen($this->rootNamespace)),'exception' =>$einstanceof \Exception ?$e :null,'cache-adapter' =>get_debug_type($this)]);
163176
}
164177
}else {
165178
foreach ($valuesas$id =>$v) {
@@ -182,7 +195,7 @@ public function commit(): bool
182195
$ok =false;
183196
$type =get_debug_type($v);
184197
$message =\sprintf('Failed to save key "{key}" of type %s%s',$type,$einstanceof \Exception ?':'.$e->getMessage() :'.');
185-
CacheItem::log($this->logger,$message, ['key' =>substr($id,\strlen($this->namespace)),'exception' =>$einstanceof \Exception ?$e :null,'cache-adapter' =>get_debug_type($this)]);
198+
CacheItem::log($this->logger,$message, ['key' =>substr($id,\strlen($this->rootNamespace)),'exception' =>$einstanceof \Exception ?$e :null,'cache-adapter' =>get_debug_type($this)]);
186199
}
187200
}
188201

‎src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
useSymfony\Component\Cache\ResettableInterface;
1818
useSymfony\Component\Cache\Traits\AbstractAdapterTrait;
1919
useSymfony\Component\Cache\Traits\ContractsTrait;
20+
useSymfony\Contracts\Cache\NamespacedPoolInterface;
2021
useSymfony\Contracts\Cache\TagAwareCacheInterface;
2122

2223
/**
@@ -30,16 +31,33 @@
3031
*
3132
* @internal
3233
*/
33-
abstractclass AbstractTagAwareAdapterimplements TagAwareAdapterInterface, TagAwareCacheInterface, LoggerAwareInterface, ResettableInterface
34+
abstractclass AbstractTagAwareAdapterimplements TagAwareAdapterInterface, TagAwareCacheInterface,AdapterInterface, NamespacedPoolInterface,LoggerAwareInterface, ResettableInterface
3435
{
3536
use AbstractAdapterTrait;
3637
use ContractsTrait;
3738

39+
/**
40+
* @internal
41+
*/
42+
protectedconstNS_SEPARATOR =':';
43+
3844
privateconstTAGS_PREFIX ="\1tags\1";
3945

4046
protectedfunction__construct(string$namespace ='',int$defaultLifetime =0)
4147
{
42-
$this->namespace ='' ===$namespace ?'' : CacheItem::validateKey($namespace).':';
48+
if ('' !==$namespace) {
49+
if (str_contains($namespace,static::NS_SEPARATOR)) {
50+
if (str_contains($namespace,static::NS_SEPARATOR.static::NS_SEPARATOR)) {
51+
thrownewInvalidArgumentException(\sprintf('Cache namespace "%s" contains empty sub-namespace.',$namespace));
52+
}
53+
CacheItem::validateKey(str_replace(static::NS_SEPARATOR,'',$namespace));
54+
}else {
55+
CacheItem::validateKey($namespace);
56+
}
57+
$this->namespace =$namespace.static::NS_SEPARATOR;
58+
}
59+
$this->rootNamespace =$this->namespace;
60+
4361
$this->defaultLifetime =$defaultLifetime;
4462
if (null !==$this->maxIdLength &&\strlen($namespace) >$this->maxIdLength -24) {
4563
thrownewInvalidArgumentException(\sprintf('Namespace must be %d chars max, %d given ("%s").',$this->maxIdLength -24,\strlen($namespace),$namespace));
@@ -70,7 +88,7 @@ static function ($key, $value, $isHit) {
7088
CacheItem::class
7189
);
7290
self::$mergeByLifetime ??= \Closure::bind(
73-
staticfunction ($deferred, &$expiredIds,$getId,$tagPrefix,$defaultLifetime) {
91+
staticfunction ($deferred, &$expiredIds,$getId,$tagPrefix,$defaultLifetime,$rootNamespace) {
7492
$byLifetime = [];
7593
$now =microtime(true);
7694
$expiredIds = [];
@@ -102,10 +120,10 @@ static function ($deferred, &$expiredIds, $getId, $tagPrefix, $defaultLifetime)
102120
$value['tag-operations'] = ['add' => [],'remove' => []];
103121
$oldTags =$item->metadata[CacheItem::METADATA_TAGS] ?? [];
104122
foreach (array_diff_key($value['tags'],$oldTags)as$addedTag) {
105-
$value['tag-operations']['add'][] =$getId($tagPrefix.$addedTag);
123+
$value['tag-operations']['add'][] =$getId($tagPrefix.$addedTag,$rootNamespace);
106124
}
107125
foreach (array_diff_key($oldTags,$value['tags'])as$removedTag) {
108-
$value['tag-operations']['remove'][] =$getId($tagPrefix.$removedTag);
126+
$value['tag-operations']['remove'][] =$getId($tagPrefix.$removedTag,$rootNamespace);
109127
}
110128
$value['tags'] =array_keys($value['tags']);
111129

@@ -168,7 +186,7 @@ protected function doDeleteYieldTags(array $ids): iterable
168186
publicfunctioncommit():bool
169187
{
170188
$ok =true;
171-
$byLifetime = (self::$mergeByLifetime)($this->deferred,$expiredIds,$this->getId(...),self::TAGS_PREFIX,$this->defaultLifetime);
189+
$byLifetime = (self::$mergeByLifetime)($this->deferred,$expiredIds,$this->getId(...),self::TAGS_PREFIX,$this->defaultLifetime,$this->rootNamespace);
172190
$retry =$this->deferred = [];
173191

174192
if ($expiredIds) {
@@ -195,7 +213,7 @@ public function commit(): bool
195213
$v =$values[$id];
196214
$type =get_debug_type($v);
197215
$message =\sprintf('Failed to save key "{key}" of type %s%s',$type,$einstanceof \Exception ?':'.$e->getMessage() :'.');
198-
CacheItem::log($this->logger,$message, ['key' =>substr($id,\strlen($this->namespace)),'exception' =>$einstanceof \Exception ?$e :null,'cache-adapter' =>get_debug_type($this)]);
216+
CacheItem::log($this->logger,$message, ['key' =>substr($id,\strlen($this->rootNamespace)),'exception' =>$einstanceof \Exception ?$e :null,'cache-adapter' =>get_debug_type($this)]);
199217
}
200218
}else {
201219
foreach ($valuesas$id =>$v) {
@@ -219,7 +237,7 @@ public function commit(): bool
219237
$ok =false;
220238
$type =get_debug_type($v);
221239
$message =\sprintf('Failed to save key "{key}" of type %s%s',$type,$einstanceof \Exception ?':'.$e->getMessage() :'.');
222-
CacheItem::log($this->logger,$message, ['key' =>substr($id,\strlen($this->namespace)),'exception' =>$einstanceof \Exception ?$e :null,'cache-adapter' =>get_debug_type($this)]);
240+
CacheItem::log($this->logger,$message, ['key' =>substr($id,\strlen($this->rootNamespace)),'exception' =>$einstanceof \Exception ?$e :null,'cache-adapter' =>get_debug_type($this)]);
223241
}
224242
}
225243

@@ -244,7 +262,7 @@ public function deleteItems(array $keys): bool
244262
try {
245263
foreach ($this->doDeleteYieldTags(array_values($ids))as$id =>$tags) {
246264
foreach ($tagsas$tag) {
247-
$tagData[$this->getId(self::TAGS_PREFIX.$tag)][] =$id;
265+
$tagData[$this->getId(self::TAGS_PREFIX.$tag,$this->rootNamespace)][] =$id;
248266
}
249267
}
250268
}catch (\Exception) {
@@ -283,7 +301,7 @@ public function invalidateTags(array $tags): bool
283301

284302
$tagIds = [];
285303
foreach (array_unique($tags)as$tag) {
286-
$tagIds[] =$this->getId(self::TAGS_PREFIX.$tag);
304+
$tagIds[] =$this->getId(self::TAGS_PREFIX.$tag,$this->rootNamespace);
287305
}
288306

289307
try {

‎src/Symfony/Component/Cache/Adapter/ArrayAdapter.php

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
useSymfony\Component\Cache\Exception\InvalidArgumentException;
2020
useSymfony\Component\Cache\ResettableInterface;
2121
useSymfony\Contracts\Cache\CacheInterface;
22+
useSymfony\Contracts\Cache\NamespacedPoolInterface;
2223

2324
/**
2425
* An in-memory cache storage.
@@ -27,13 +28,14 @@
2728
*
2829
* @author Nicolas Grekas <p@tchwork.com>
2930
*/
30-
class ArrayAdapterimplements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
31+
class ArrayAdapterimplements AdapterInterface, CacheInterface,NamespacedPoolInterface,LoggerAwareInterface, ResettableInterface
3132
{
3233
use LoggerAwareTrait;
3334

3435
privatearray$values = [];
3536
privatearray$tags = [];
3637
privatearray$expiries = [];
38+
privatearray$subPools = [];
3739

3840
privatestatic\Closure$createCacheItem;
3941

@@ -226,16 +228,38 @@ public function clear(string $prefix = ''): bool
226228
}
227229
}
228230

229-
if ($this->values) {
230-
returntrue;
231-
}
231+
returntrue;
232+
}
233+
234+
foreach ($this->subPoolsas$pool) {
235+
$pool->clear();
232236
}
233237

234-
$this->values =$this->tags =$this->expiries = [];
238+
$this->subPools =$this->values =$this->tags =$this->expiries = [];
235239

236240
returntrue;
237241
}
238242

243+
publicfunctionwithSubNamespace(string$namespace):static
244+
{
245+
CacheItem::validateKey($namespace);
246+
247+
$subPools =$this->subPools;
248+
249+
if (isset($subPools[$namespace])) {
250+
return$subPools[$namespace];
251+
}
252+
253+
$this->subPools = [];
254+
$clone =clone$this;
255+
$clone->clear();
256+
257+
$subPools[$namespace] =$clone;
258+
$this->subPools =$subPools;
259+
260+
return$clone;
261+
}
262+
239263
/**
240264
* Returns all cached values, with cache miss as null.
241265
*/
@@ -263,6 +287,13 @@ public function reset(): void
263287
$this->clear();
264288
}
265289

290+
publicfunction__clone()
291+
{
292+
foreach ($this->subPoolsas$i =>$pool) {
293+
$this->subPools[$i] =clone$pool;
294+
}
295+
}
296+
266297
privatefunctiongenerateItems(array$keys,float$now,\Closure$f):\Generator
267298
{
268299
foreach ($keysas$i =>$key) {

‎src/Symfony/Component/Cache/Adapter/ChainAdapter.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
usePsr\Cache\CacheItemInterface;
1515
usePsr\Cache\CacheItemPoolInterface;
1616
useSymfony\Component\Cache\CacheItem;
17+
useSymfony\Component\Cache\Exception\BadMethodCallException;
1718
useSymfony\Component\Cache\Exception\InvalidArgumentException;
1819
useSymfony\Component\Cache\PruneableInterface;
1920
useSymfony\Component\Cache\ResettableInterface;
2021
useSymfony\Component\Cache\Traits\ContractsTrait;
2122
useSymfony\Contracts\Cache\CacheInterface;
23+
useSymfony\Contracts\Cache\NamespacedPoolInterface;
2224
useSymfony\Contracts\Service\ResetInterface;
2325

2426
/**
@@ -29,7 +31,7 @@
2931
*
3032
* @author Kévin Dunglas <dunglas@gmail.com>
3133
*/
32-
class ChainAdapterimplements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
34+
class ChainAdapterimplements AdapterInterface, CacheInterface,NamespacedPoolInterface,PruneableInterface, ResettableInterface
3335
{
3436
use ContractsTrait;
3537

@@ -280,6 +282,23 @@ public function prune(): bool
280282
return$pruned;
281283
}
282284

285+
publicfunctionwithSubNamespace(string$namespace):static
286+
{
287+
$clone =clone$this;
288+
$adapters = [];
289+
290+
foreach ($this->adaptersas$adapter) {
291+
if (!$adapterinstanceof NamespacedPoolInterface) {
292+
thrownewBadMethodCallException('All adapters must implement NamespacedPoolInterface to support namespaces.');
293+
}
294+
295+
$adapters[] =$adapter->withSubNamespace($namespace);
296+
}
297+
$clone->adapters =$adapters;
298+
299+
return$clone;
300+
}
301+
283302
publicfunctionreset():void
284303
{
285304
foreach ($this->adaptersas$adapter) {

‎src/Symfony/Component/Cache/Adapter/DoctrineDbalAdapter.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,17 +335,17 @@ protected function doSave(array $values, int $lifetime): array|bool
335335
/**
336336
* @internal
337337
*/
338-
protectedfunctiongetId(mixed$key):string
338+
protectedfunctiongetId(mixed$key, ?string$namespace =null):string
339339
{
340340
if ('pgsql' !==$this->platformName ??=$this->getPlatformName()) {
341-
returnparent::getId($key);
341+
returnparent::getId($key,$namespace);
342342
}
343343

344344
if (str_contains($key,"\0") ||str_contains($key,'%') || !preg_match('//u',$key)) {
345345
$key =rawurlencode($key);
346346
}
347347

348-
returnparent::getId($key);
348+
returnparent::getId($key,$namespace);
349349
}
350350

351351
privatefunctiongetPlatformName():string

‎src/Symfony/Component/Cache/Adapter/NullAdapter.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
usePsr\Cache\CacheItemInterface;
1515
useSymfony\Component\Cache\CacheItem;
1616
useSymfony\Contracts\Cache\CacheInterface;
17+
useSymfony\Contracts\Cache\NamespacedPoolInterface;
1718

1819
/**
1920
* @author Titouan Galopin <galopintitouan@gmail.com>
2021
*/
21-
class NullAdapterimplements AdapterInterface, CacheInterface
22+
class NullAdapterimplements AdapterInterface, CacheInterface, NamespacedPoolInterface
2223
{
2324
privatestatic\Closure$createCacheItem;
2425

@@ -94,6 +95,11 @@ public function delete(string $key): bool
9495
return$this->deleteItem($key);
9596
}
9697

98+
publicfunctionwithSubNamespace(string$namespace):static
99+
{
100+
returnclone$this;
101+
}
102+
97103
privatefunctiongenerateItems(array$keys):\Generator
98104
{
99105
$f =self::$createCacheItem;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp