symfony: [FrameworkBundle] [Cache] cache:clear warms up cache incorrectly

Q A
Bug report? yes
Feature request? no
BC Break report? yes
RFC? no
Symfony version >4.0.3

After update Symfony to version 4.0.3 (4.0.4 -the same) cache:clear command (with implicit cache warming) warms up cache incorrectly. As i can compare with 4.0.2 cache folder some dependencies is not warmed.

4.0.3

root@bacac0721dd9:/var/www/symfony# bin/console ca:cl -e=prod
root@bacac0721dd9:/var/www/symfony# ls -1 var/cache/prod/
ContainerM4N54hq
annotations.map
srcProdProjectContainer.php
srcProdProjectContainer.php.meta
srcProdProjectContainerUrlGenerator.php
srcProdProjectContainerUrlGenerator.php.meta
srcProdProjectContainerUrlMatcher.php
srcProdProjectContainerUrlMatcher.php.meta
templates.php

4.0.2

root@bacac0721dd9:/var/www/symfony# bin/console ca:cl -e=prod
root@bacac0721dd9:/var/www/symfony# ls -1 var/cache/prod/
ContainerW99Fklq
annotations.map
annotations.php
doctrine
easy_admin
pools
serialization.php
srcProdProjectContainer.php
srcProdProjectContainer.php.meta
srcProdProjectContainerUrlGenerator.php
srcProdProjectContainerUrlGenerator.php.meta
srcProdProjectContainerUrlMatcher.php
srcProdProjectContainerUrlMatcher.php.meta
templates.php
translations
twig
validation.php

For develop env it isn’t critical, but for production it is. ps As workaround i used bin/console cache:warmup -e=prod after

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 20 (8 by maintainers)

Commits related to this issue

Most upvoted comments

Hmm, looking into this some more, I think I’ve got an idea of what’s going on. The crux of the issue is that the cache warmer is being passed the cache dir (prod) instead of the warmup dir (pro_), so warmup cache is generated in the wrong directory. However, this only happens when the warmup container dumps with the same content hash as the previously cached container in prod. Because the appProdProjectContainer classes are generated with the same namespace, e.g. ContainerBnhddds, but rely on their current directory to generate the right target dirs, an instance of the container in the prod folder is returned which gives a kernel.cache_dir value mis-match.

  1. Kernel boots for the first time when running the cache:clear command, var/cache/prod/appProdProjectContainer.php is included in Kernel::initializeContainer, which returns a new instance of \ContainerBnhddds\appProdProjectContainer.
  2. Later on, the kernel is rebooted with CacheClearCommand::warmup, which compiles the container as the warmup cache isn’t fresh (var/cache/pro_/appProdProjectContainer.php doesn’t yet exist).
  3. The new container has the same build ID, so while var/cache/pro_/appProdProjectContainer.php is required, an instance of the \ContainerBnhddds\appProdProjectContainer class in prod is returned.
  4. The cache warmer now generates cache in prod, but since pro_ is later renamed to prod in CacheClearCommand::execute, any generated files are lost.

I hope this makes sense, I’ve been debugging for a good few hours since I noticed that one 3.4 project exhibited this behaviour and another didn’t, which lead me to https://github.com/doctrine/DoctrineBundle/issues/761 and this issue. I’m not sure why only one project always generates a different build ID each time, or if it’sen meant to, but this clash is certainly causing warmup cache to be put in the wrong directory.

it would still be great to reproduce this to at least make the failure not silent.

@blackandred look at my previously comment. In dev environment your application work, because in dev symfony can warm up services on the fly. For test please try following command: bin/console cache:clear --env=dev && ls -l var/cache/dev It show you all files in cache. After that open your application (or just do bin/console cache:warmup --env=dev) and compare cache file list with previous one.

@lstrojny excuse me, but after #26128 the time is optionally deterministic. For guys who doesn’t care about reproducible builds (time will difference each run) solution will works fine. bin/console ca:cl -e=prod will works correct. Guys who care about reproducible builds, have to fix the build time in parameters, so they will have the same container name (unfortunately, bin/console ca:cl -e=prod will works incorrect, the same as at now 😦 )

Isn’t the problem in the cache warmer because the wrong path is passed?

roughly speaking - yes. I try explain a bit. When bin/console ca:cl -e=prod started, before command executing Symfony create and dump old kernel in /var/cache/prod/srcProdProjectContainer.php, and then load class via new ContainerA9d1Z7x\srcProdProjectContainer into PHP memory. After that CacheClearCommand tried to load /var/cache/pro_/srcProdProjectContainer.php witch create new instance of /var/cache/pro_/ContainerA9d1Z7x/srcProdProjectContainer.php , but PHP already has \ContainerA9d1Z7x\srcProdProjectContainer (from /var/cache/prod path) and return it.

So, i think, as PHP can not unload classes from memory, we cant resolve this issue without changing class name.

Hi @xabbuh.

I’ve tried to reproduce issue on small example (framework + templating + doctrine). The bug isn’t reproduced. Looks like some another third party bundle in my project failed while warmed and console command just silently stopped. I’m think this behavior was introduced with #25117. While i was trying play with composer dependencies broken lib was updated and fixed, and bug no more reproduced.