Description
Symfony version(s) affected
6.2.5
Description
Current behaviour
Let's create following cache pool config:
framework:
cache:
prefix_seed: my-amazing-project
app: cache.app.custom
system: cache.adapter.system
pools:
cache.app.custom:
adapters: cache.adapter.apcu
clearer: cache.app_clearer
tags: true
cache.app.vokativ:
adapter: cache.app
cache.app.user:
adapter: cache.app
In this case every pool referencing cache.app
has its own namespace for generating keys to APCU, as declared in documentation, see bellow.
If I save item with key ipsum
to cache cache.app.vokativ
with value A
and another item with the same key ipsum
and value B
to cache cache.app.user
, cache records do not colide and from cache cache.app.vokativ
is returned A
value, from cache cache.app.user
is returned B
value, even if pools share the same backend cache.app
(= cache.app.custom
).
Now, let's have following buggy config:
We will modify main cache.app.custom
to use Chain Adapter
with APCU and Redis.
framework:
cache:
prefix_seed: my-amazing-project
app: cache.app.custom
system: cache.adapter.system
default_redis_provider: '%env(resolve:REDIS_DSN)%'
pools:
cache.app.custom:
adapters:
- cache.adapter.apcu
- cache.adapter.redis_tag_aware
clearer: cache.app_clearer
tags: true
cache.app.vokativ:
adapter: cache.app
cache.app.user:
adapter: cache.app
In this case every pool referencing cache.app
has THE SAME NAMESPACE for generating keys saved to the cache.app
pool.
If I save item with key ipsum
with value A
to cache cache.app.vokativ
and another item with the same key ipsum
and value B
to cache cache.app.user
, cache records do colide and from cache cache.app.vokativ
is returned A
value, from cache cache.app.user
is returned A
value, when the pools share the same backend cache.app
(= cache.app.custom
).
I have checked it manually in Redis and the namespace for keys is the same. It is happening only, if parent pool is the chain type pool.
The problem is happing here -> https://github.com/symfony/cache/blob/6.2/DependencyInjection/CachePoolPass.php#L58 between lines 58 and 65, which results that $tags[0]['name']
contains Service ID of Chained pool... so $id
of pool is never used in this case. I do not know the reason, why the code designed this way... but anyway it is not corresponding to actual documentation.
From my point of view, even if I use chain adapter as parent adapter for new pool, new namespace should be introduced, otherwise cache key pools will colide and it will lead to unexpected cache pool results.
Expected behaviour
Symfony Docs -> Cache -> Creating Custom (Namespaced) Pools:
Each pool manages a set of independent cache keys: keys from different pools never collide, even if they share the same backend. This is achieved by prefixing keys with a namespace that's generated by hashing the name of the pool, the name of the cache adapter class and a configurable seed that defaults to the project directory and compiled container class.
How to reproduce
Use following config to reproduce problem. You can use any kind of cache adapters contained in the chain.
framework:
cache:
prefix_seed: my-amazing-project
app: cache.app.custom
system: cache.adapter.system
default_redis_provider: '%env(resolve:REDIS_DSN)%'
pools:
cache.app.custom:
adapters:
- cache.adapter.apcu
- cache.adapter.redis_tag_aware
clearer: cache.app_clearer
tags: true
cache.app.vokativ:
adapter: cache.app
cache.app.user:
adapter: cache.app
Possible Solution
Change the behavior in the loop beginning here https://github.com/symfony/cache/blob/6.2/DependencyInjection/CachePoolPass.php#L58