Skip to content

Commit

Permalink
[DI] add tags container.preload/.no_preload to declare extra clas…
Browse files Browse the repository at this point in the history
…ses to preload/services to not preload
  • Loading branch information
nicolas-grekas committed Mar 25, 2020
1 parent 4dabd00 commit b62ee86
Show file tree
Hide file tree
Showing 27 changed files with 124 additions and 25 deletions.
Expand Up @@ -32,6 +32,8 @@ class UnusedTagsPass implements CompilerPassInterface
'container.env_var_loader',
'container.env_var_processor',
'container.hot_path',
'container.no_preload',
'container.preload',
'container.reversible',
'container.service_locator',
'container.service_locator_context',
Expand Down
Expand Up @@ -408,7 +408,8 @@ public function load(array $configs, ContainerBuilder $container)
}

$container->registerForAutoconfiguration(Command::class)
->addTag('console.command');
->addTag('console.command')
->addTag('container.no_preload');
$container->registerForAutoconfiguration(ResourceCheckerInterface::class)
->addTag('config_cache.resource_checker');
$container->registerForAutoconfiguration(EnvVarLoaderInterface::class)
Expand All @@ -434,7 +435,8 @@ public function load(array $configs, ContainerBuilder $container)
$container->registerForAutoconfiguration(CacheClearerInterface::class)
->addTag('kernel.cache_clearer');
$container->registerForAutoconfiguration(CacheWarmerInterface::class)
->addTag('kernel.cache_warmer');
->addTag('kernel.cache_warmer')
->addTag('container.no_preload');
$container->registerForAutoconfiguration(EventSubscriberInterface::class)
->addTag('kernel.event_subscriber');
$container->registerForAutoconfiguration(LocaleAwareInterface::class)
Expand Down
Expand Up @@ -34,6 +34,7 @@
</service>

<service id="annotations.cache_warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer">
<tag name="container.no_preload" />
<argument type="service" id="annotations.reader" />
<argument>%kernel.cache_dir%/annotations.php</argument>
<argument>#^Symfony\\(?:Component\\HttpKernel\\|Bundle\\FrameworkBundle\\Controller\\(?!.*Controller$))#</argument>
Expand Down
Expand Up @@ -20,6 +20,7 @@
<argument>cache.serializer</argument>
</argument>
<tag name="kernel.cache_warmer" priority="64" />
<tag name="container.no_preload" />
</service>
</services>
</container>
Expand Up @@ -11,10 +11,12 @@
<argument type="service" id="logger" on-invalid="null" />
<tag name="kernel.event_subscriber" />
<tag name="monolog.logger" channel="console" />
<tag name="container.no_preload" />
</service>

<service id="console.suggest_missing_package_subscriber" class="Symfony\Bundle\FrameworkBundle\EventListener\SuggestMissingPackageSubscriber">
<tag name="kernel.event_subscriber" />
<tag name="container.no_preload" />
</service>

<service id="console.command.about" class="Symfony\Bundle\FrameworkBundle\Command\AboutCommand">
Expand Down
Expand Up @@ -101,6 +101,7 @@
<service id="router.cache_warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\RouterCacheWarmer">
<tag name="container.service_subscriber" id="router" />
<tag name="kernel.cache_warmer" />
<tag name="container.no_preload" />
<argument type="service" id="Psr\Container\ContainerInterface" />
</service>

Expand Down
Expand Up @@ -107,6 +107,7 @@
<argument type="collection" /><!-- Loaders injected by the extension -->
<argument>%serializer.mapping.cache.file%</argument>
<tag name="kernel.cache_warmer" />
<tag name="container.no_preload" />
</service>

<service id="serializer.mapping.cache.symfony" class="Psr\Cache\CacheItemPoolInterface">
Expand Down
Expand Up @@ -66,6 +66,7 @@
<service id="Symfony\Component\HttpFoundation\UrlHelper" alias="url_helper" />

<service id="cache_warmer" class="Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate" public="true">
<tag name="container.no_preload" />
<argument type="tagged_iterator" tag="kernel.cache_warmer" />
<argument>%kernel.debug%</argument>
<argument>%kernel.cache_dir%/%kernel.container_class%Deprecations.log</argument>
Expand Down
Expand Up @@ -139,6 +139,7 @@
<service id="translation.warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\TranslationsCacheWarmer">
<tag name="container.service_subscriber" id="translator" />
<tag name="kernel.cache_warmer" />
<tag name="container.no_preload" />
<argument type="service" id="Psr\Container\ContainerInterface" />
</service>
</services>
Expand Down
Expand Up @@ -36,6 +36,7 @@
<argument type="service" id="validator.builder" />
<argument>%validator.mapping.cache.file%</argument>
<tag name="kernel.cache_warmer" />
<tag name="container.no_preload" />
</service>

<service id="validator.mapping.cache.adapter" class="Symfony\Component\Cache\Adapter\PhpArrayAdapter">
Expand Down
Expand Up @@ -218,6 +218,7 @@
<!-- Cache Warmers -->
<service id="security.cache_warmer.expression" class="Symfony\Bundle\SecurityBundle\CacheWarmer\ExpressionCacheWarmer">
<tag name="kernel.cache_warmer" />
<tag name="container.no_preload" />
<argument type="collection" /> <!-- expressions -->
<argument type="service" id="security.expression_language" />
</service>
Expand Down
9 changes: 9 additions & 0 deletions src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
Expand Up @@ -18,6 +18,14 @@
<argument type="service" id="twig.runtime_loader" />
</call>
<configurator service="twig.configurator.environment" method="configure" />
<tag name="container.preload" class="Twig\Cache\FilesystemCache" />
<tag name="container.preload" class="Twig\Extension\CoreExtension" />
<tag name="container.preload" class="Twig\Extension\EscaperExtension" />
<tag name="container.preload" class="Twig\Extension\OptimizerExtension" />
<tag name="container.preload" class="Twig\Extension\StagingExtension" />
<tag name="container.preload" class="Twig\ExtensionSet" />
<tag name="container.preload" class="Twig\Template" />
<tag name="container.preload" class="Twig\TemplateWrapper" />
</service>
<service id="Twig_Environment" alias="twig" />
<service id="Twig\Environment" alias="twig" />
Expand All @@ -37,6 +45,7 @@

<service id="twig.template_cache_warmer" class="Symfony\Bundle\TwigBundle\CacheWarmer\TemplateCacheWarmer">
<tag name="kernel.cache_warmer" />
<tag name="container.no_preload" />
<tag name="container.service_subscriber" id="twig" />
<argument type="service" id="Psr\Container\ContainerInterface" />
<argument type="service" id="twig.template_iterator" />
Expand Down
14 changes: 0 additions & 14 deletions src/Symfony/Bundle/TwigBundle/TwigBundle.php
Expand Up @@ -19,20 +19,6 @@
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Twig\Cache\FilesystemCache;
use Twig\Extension\CoreExtension;
use Twig\Extension\EscaperExtension;
use Twig\Extension\OptimizerExtension;
use Twig\Extension\StagingExtension;
use Twig\ExtensionSet;

// Help opcache.preload discover always-needed symbols
class_exists(FilesystemCache::class);
class_exists(CoreExtension::class);
class_exists(EscaperExtension::class);
class_exists(OptimizerExtension::class);
class_exists(StagingExtension::class);
class_exists(ExtensionSet::class);

/**
* Bundle.
Expand Down
Expand Up @@ -28,11 +28,13 @@ class AddConsoleCommandPass implements CompilerPassInterface
{
private $commandLoaderServiceId;
private $commandTag;
private $noPreloadTag;

public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command')
public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command', string $noPreloadTag = 'container.no_preload')
{
$this->commandLoaderServiceId = $commandLoaderServiceId;
$this->commandTag = $commandTag;
$this->noPreloadTag = $noPreloadTag;
}

public function process(ContainerBuilder $container)
Expand All @@ -44,6 +46,7 @@ public function process(ContainerBuilder $container)

foreach ($commandServices as $id => $tags) {
$definition = $container->getDefinition($id);
$definition->addTag($this->noPreloadTag);
$class = $container->getParameterBag()->resolveValue($definition->getClass());

if (isset($tags[0]['command'])) {
Expand Down Expand Up @@ -91,6 +94,7 @@ public function process(ContainerBuilder $container)
$container
->register($this->commandLoaderServiceId, ContainerCommandLoader::class)
->setPublic(true)
->addTag($this->noPreloadTag)
->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]);

$container->setParameter('console.command.ids', $serviceIds);
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/DependencyInjection/CHANGELOG.md
Expand Up @@ -7,6 +7,7 @@ CHANGELOG
* added support to autowire public typed properties in php 7.4
* added support for defining method calls, a configurator, and property setters in `InlineServiceConfigurator`
* added possibility to define abstract service arguments
* added tags `container.preload`/`.no_preload` to declare extra classes to preload/services to not preload

5.0.0
-----
Expand Down
27 changes: 19 additions & 8 deletions src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
Expand Up @@ -78,6 +78,7 @@ class PhpDumper extends Dumper
private $namespace;
private $asFiles;
private $hotPathTag;
private $preloadTag;
private $inlineFactories;
private $inlineRequires;
private $inlinedRequires = [];
Expand Down Expand Up @@ -143,6 +144,7 @@ public function dump(array $options = [])
'as_files' => false,
'debug' => true,
'hot_path_tag' => 'container.hot_path',
'preload_tags' => ['container.preload', 'container.no_preload'],
'inline_factories_parameter' => 'container.dumper.inline_factories',
'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
'preload_classes' => [],
Expand All @@ -154,6 +156,7 @@ public function dump(array $options = [])
$this->namespace = $options['namespace'];
$this->asFiles = $options['as_files'];
$this->hotPathTag = $options['hot_path_tag'];
$this->preloadTags = $options['preload_tags'];
$this->inlineFactories = $this->asFiles && $options['inline_factories_parameter'] && (!$this->container->hasParameter($options['inline_factories_parameter']) || $this->container->getParameter($options['inline_factories_parameter']));
$this->inlineRequires = $options['inline_class_loader_parameter'] && ($this->container->hasParameter($options['inline_class_loader_parameter']) ? $this->container->getParameter($options['inline_class_loader_parameter']) : (\PHP_VERSION_ID < 70400 || $options['debug']));
$this->serviceLocatorTag = $options['service_locator_tag'];
Expand Down Expand Up @@ -560,7 +563,7 @@ private function addServiceInclude(string $cId, Definition $definition): string
$lineage = [];
foreach ($this->inlinedDefinitions as $def) {
if (!$def->isDeprecated()) {
foreach ($this->getClasses($def) as $class) {
foreach ($this->getClasses($def, $cId) as $class) {
$this->collectLineage($class, $lineage);
}
}
Expand All @@ -572,7 +575,7 @@ private function addServiceInclude(string $cId, Definition $definition): string
&& $this->container->has($id)
&& $this->isTrivialInstance($def = $this->container->findDefinition($id))
) {
foreach ($this->getClasses($def) as $class) {
foreach ($this->getClasses($def, $cId) as $class) {
$this->collectLineage($class, $lineage);
}
}
Expand Down Expand Up @@ -824,9 +827,9 @@ protected function {$methodName}($lazyInitialization)

if ($definition->isDeprecated()) {
$code .= sprintf(" trigger_deprecation('', '', %s);\n\n", $this->export($definition->getDeprecationMessage($id)));
} else {
} elseif (!$definition->hasTag($this->preloadTags[1])) {
foreach ($this->inlinedDefinitions as $def) {
foreach ($this->getClasses($def) as $class) {
foreach ($this->getClasses($def, $id) as $class) {
$this->preload[$class] = $class;
}
}
Expand Down Expand Up @@ -988,10 +991,10 @@ private function addServices(array &$services = null): string
foreach ($definitions as $id => $definition) {
if (!$definition->isSynthetic()) {
$services[$id] = $this->addService($id, $definition);
} else {
} elseif (!$definition->hasTag($this->preloadTags[1])) {
$services[$id] = null;

foreach ($this->getClasses($definition) as $class) {
foreach ($this->getClasses($definition, $id) as $class) {
$this->preload[$class] = $class;
}
}
Expand Down Expand Up @@ -1376,7 +1379,7 @@ private function addInlineRequires(): string
$inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]);

foreach ($inlinedDefinitions as $def) {
foreach ($this->getClasses($def) as $class) {
foreach ($this->getClasses($def, $id) as $class) {
$this->collectLineage($class, $lineage);
}
}
Expand Down Expand Up @@ -2099,11 +2102,19 @@ private function getAutoloadFile(): ?string
return null;
}

private function getClasses(Definition $definition): array
private function getClasses(Definition $definition, string $id): array
{
$classes = [];

while ($definition instanceof Definition) {
foreach ($definition->getTag($this->preloadTags[0]) as $tag) {
if (!isset($tag['class'])) {
throw new InvalidArgumentException(sprintf('Missing attribute "class" on tag "%s" for service "%s".', $this->preloadTags[0], $id));
}

$classes[] = trim($tag['class'], '\\');
}

$classes[] = trim($definition->getClass(), '\\');
$factory = $definition->getFactory();

Expand Down
Expand Up @@ -134,6 +134,10 @@
->args([new Reference('errored_definition', ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE)])
->public();
$s->set('errored_definition', 'stdClass')->private();
$s->set('preload_sidekick', 'stdClass')
->tag('container.preload', ['class' => 'Some\Sidekick1'])
->tag('container.preload', ['class' => 'Some\Sidekick2'])
->public();

$s->alias('alias_for_foo', 'foo')->private()->public();
$s->alias('alias_for_alias', ref('alias_for_foo'));
Expand Down
Expand Up @@ -187,4 +187,9 @@
$container->register('errored_definition', 'stdClass')
->addError('Service "errored_definition" is broken.');

$container->register('preload_sidekick', 'stdClass')
->setPublic(true)
->addTag('container.preload', ['class' => 'Some\Sidekick1'])
->addTag('container.preload', ['class' => 'Some\Sidekick2']);

return $container;
Expand Up @@ -36,6 +36,7 @@ digraph sc {
node_tagged_iterator [label="tagged_iterator\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_runtime_error [label="runtime_error\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_errored_definition [label="errored_definition\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_preload_sidekick [label="preload_sidekick\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"];
node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"];
node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"];
Expand Down
Expand Up @@ -308,6 +308,16 @@ $this->factories['non_shared_foo'] = function () {

return $this->factories['non_shared_foo']();

[Container%s/getPreloadSidekickService.php] => <?php

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
// Returns the public 'preload_sidekick' shared service.

return $this->services['preload_sidekick'] = new \stdClass();

[Container%s/getRuntimeErrorService.php] => <?php

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
Expand Down Expand Up @@ -412,6 +422,7 @@ class ProjectServiceContainer extends Container
'method_call1' => 'getMethodCall1Service.php',
'new_factory_service' => 'getNewFactoryServiceService.php',
'non_shared_foo' => 'getNonSharedFooService.php',
'preload_sidekick' => 'getPreloadSidekickService.php',
'runtime_error' => 'getRuntimeErrorService.php',
'service_from_static_method' => 'getServiceFromStaticMethodService.php',
'tagged_iterator' => 'getTaggedIteratorService.php',
Expand Down Expand Up @@ -542,6 +553,8 @@ $classes[] = 'Foo';
$classes[] = 'LazyContext';
$classes[] = 'FooBarBaz';
$classes[] = 'FactoryClass';
$classes[] = 'Some\Sidekick1';
$classes[] = 'Some\Sidekick2';
$classes[] = 'Request';
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';

Expand Down
Expand Up @@ -48,6 +48,7 @@ public function __construct()
'lazy_context_ignore_invalid_ref' => 'getLazyContextIgnoreInvalidRefService',
'method_call1' => 'getMethodCall1Service',
'new_factory_service' => 'getNewFactoryServiceService',
'preload_sidekick' => 'getPreloadSidekickService',
'runtime_error' => 'getRuntimeErrorService',
'service_from_static_method' => 'getServiceFromStaticMethodService',
'tagged_iterator' => 'getTaggedIteratorService',
Expand Down Expand Up @@ -362,6 +363,16 @@ protected function getNewFactoryServiceService()
return $instance;
}

/**
* Gets the public 'preload_sidekick' shared service.
*
* @return \stdClass
*/
protected function getPreloadSidekickService()
{
return $this->services['preload_sidekick'] = new \stdClass();
}

/**
* Gets the public 'runtime_error' shared service.
*
Expand Down

0 comments on commit b62ee86

Please sign in to comment.