feature #36599 [HttpKernel] make kernels implementing WarmableInterface be part of the cache warmup stage (nicolas-grekas)

This PR was merged into the 5.1-dev branch.

Discussion
----------

[HttpKernel] make kernels implementing `WarmableInterface` be part of the cache warmup stage

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | -

This allows your kernel to return extra classes to preload also (which was my main motivation for creating this PR actually.)

```php
// ...
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
// ...

class Kernel ... implements ..., WarmableInterface
{
    // ...

    public function warmUp(string $cacheDir): array
    {
        // ...

        return [
            SomeClassToPreload::class,
            AnotherClassClassToPreload::class,
            $cacheDir.'/some-file-to-preload.php',
            // ...
        ];
    }

    // ...
}
```

Commits
-------

649e530356 [HttpKernel] make kernels implementing `WarmableInterface` be part of the cache warmup stage
This commit is contained in:
Fabien Potencier 2020-05-03 16:39:00 +02:00
commit 07a0334947
3 changed files with 27 additions and 6 deletions

View File

@ -6,6 +6,7 @@ CHANGELOG
* made `WarmableInterface::warmUp()` return a list of classes or files to preload on PHP 7.4+; * made `WarmableInterface::warmUp()` return a list of classes or files to preload on PHP 7.4+;
not returning an array is deprecated not returning an array is deprecated
* made kernels implementing `WarmableInterface` be part of the cache warmup stage
* deprecated support for `service:action` syntax to reference controllers, use `serviceOrFqcn::method` instead * deprecated support for `service:action` syntax to reference controllers, use `serviceOrFqcn::method` instead
* allowed using public aliases to reference controllers * allowed using public aliases to reference controllers
* added session usage reporting when the `_stateless` attribute of the request is set to `true` * added session usage reporting when the `_stateless` attribute of the request is set to `true`

View File

@ -35,6 +35,7 @@ use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use Symfony\Component\HttpKernel\Config\FileLocator; use Symfony\Component\HttpKernel\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass; use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass;
use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
@ -566,12 +567,14 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
touch($oldContainerDir.'.legacy'); touch($oldContainerDir.'.legacy');
} }
if ($this->container->has('cache_warmer')) { $preload = $this instanceof WarmableInterface ? (array) $this->warmUp($this->container->getParameter('kernel.cache_dir')) : [];
$preload = (array) $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
if ($preload && method_exists(Preloader::class, 'append') && file_exists($preloadFile = $cacheDir.'/'.$class.'.preload.php')) { if ($this->container->has('cache_warmer')) {
Preloader::append($preloadFile, $preload); $preload = array_merge($preload, (array) $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')));
} }
if ($preload && method_exists(Preloader::class, 'append') && file_exists($preloadFile = $cacheDir.'/'.$class.'.preload.php')) {
Preloader::append($preloadFile, $preload);
} }
} }

View File

@ -19,6 +19,7 @@ use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass; use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass;
use Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter; use Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter;
use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernelInterface;
@ -480,6 +481,14 @@ EOF;
$this->assertTrue($kernel->getContainer()->getParameter('test.processed')); $this->assertTrue($kernel->getContainer()->getParameter('test.processed'));
} }
public function testWarmup()
{
$kernel = new CustomProjectDirKernel();
$kernel->boot();
$this->assertTrue($kernel->warmedUp);
}
public function testServicesResetter() public function testServicesResetter()
{ {
$httpKernelMock = $this->getMockBuilder(HttpKernelInterface::class) $httpKernelMock = $this->getMockBuilder(HttpKernelInterface::class)
@ -603,8 +612,9 @@ class TestKernel implements HttpKernelInterface
} }
} }
class CustomProjectDirKernel extends Kernel class CustomProjectDirKernel extends Kernel implements WarmableInterface
{ {
public $warmedUp = false;
private $baseDir; private $baseDir;
private $buildContainer; private $buildContainer;
private $httpKernel; private $httpKernel;
@ -631,6 +641,13 @@ class CustomProjectDirKernel extends Kernel
return __DIR__.'/Fixtures'; return __DIR__.'/Fixtures';
} }
public function warmUp(string $cacheDir): array
{
$this->warmedUp = true;
return [];
}
protected function build(ContainerBuilder $container) protected function build(ContainerBuilder $container)
{ {
if ($build = $this->buildContainer) { if ($build = $this->buildContainer) {