Skip to content

Commit 6505049

Browse files
mvrhovsroze
authored andcommitted
Handlers should be lazy loaded
1 parent ca246c0 commit 6505049

File tree

3 files changed

+65
-6
lines changed

3 files changed

+65
-6
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/message.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
<service id="Symfony\Component\Message\MessageBusInterface" alias="message_bus" />
1616

1717
<!-- Handlers -->
18-
<service id="message.handler_resolver" class="Symfony\Component\Message\HandlerLocator">
19-
<argument type="collection" /> <!-- Message to handler mapping -->
18+
<service id="message.handler_resolver" class="Symfony\Component\Message\ContainerHandlerLocator">
19+
<argument type="service" id="service_container"/>
2020
</service>
2121

2222
<service id="message.middleware.call_message_handler" class="Symfony\Component\Message\Middleware\HandleMessageMiddleware">
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Message;
13+
14+
use Psr\Container\ContainerInterface;
15+
use Symfony\Component\Message\Exception\NoHandlerForMessageException;
16+
17+
/**
18+
* @author Miha Vrhovnik <miha.vrhovnik@gmail.com>
19+
*/
20+
class ContainerHandlerLocator implements HandlerLocatorInterface
21+
{
22+
/**
23+
* @var ContainerInterface
24+
*/
25+
private $serviceLocator;
26+
27+
public function __construct(ContainerInterface $serviceLocator)
28+
{
29+
$this->serviceLocator = $serviceLocator;
30+
}
31+
32+
public function resolve($message): callable
33+
{
34+
$messageKey = get_class($message);
35+
36+
if (!$this->serviceLocator->has($messageKey)) {
37+
throw new NoHandlerForMessageException(sprintf('No handler for message "%s"', $messageKey));
38+
}
39+
40+
return $this->serviceLocator->get($messageKey);
41+
}
42+
}

src/Symfony/Component/Message/DependencyInjection/MessagePass.php

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313

1414
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1515
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
16+
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
1617
use Symfony\Component\DependencyInjection\ContainerBuilder;
18+
use Symfony\Component\DependencyInjection\Definition;
1719
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
1820
use Symfony\Component\DependencyInjection\Reference;
21+
use Symfony\Component\Message\Handler\MessageHandlerCollection;
1922

2023
/**
2124
* @author Samuel Roze <samuel.roze@gmail.com>
@@ -53,11 +56,10 @@ public function process(ContainerBuilder $container)
5356
$busDefinition = $container->getDefinition($this->messageBusService);
5457
$busDefinition->replaceArgument(0, $middlewares);
5558

56-
$handlerResolver = $container->getDefinition($this->messageHandlerResolverService);
57-
$handlerResolver->replaceArgument(0, $this->findHandlers($container));
59+
$this->registerHandlers($container);
5860
}
5961

60-
private function findHandlers(ContainerBuilder $container): array
62+
private function registerHandlers(ContainerBuilder $container)
6163
{
6264
$handlersByMessage = array();
6365

@@ -79,7 +81,22 @@ private function findHandlers(ContainerBuilder $container): array
7981
$handlersByMessage[$message] = call_user_func_array('array_merge', $handlersByMessage[$message]);
8082
}
8183

82-
return $handlersByMessage;
84+
$definitions = array();
85+
foreach ($handlersByMessage as $message => $handlers) {
86+
if (1 === count($handlers)) {
87+
$handlersByMessage[$message] = current($handlers);
88+
} else {
89+
$d = new Definition(MessageHandlerCollection::class, array($handlers));
90+
$d->setPrivate(true);
91+
$serviceId = hash('sha1', $message);
92+
$definitions[$serviceId] = $d;
93+
$handlersByMessage[$message] = new Reference($serviceId);
94+
}
95+
}
96+
$container->addDefinitions($definitions);
97+
98+
$handlerResolver = $container->getDefinition($this->messageHandlerResolverService);
99+
$handlerResolver->replaceArgument(0, ServiceLocatorTagPass::register($container, $handlersByMessage));
83100
}
84101

85102
private function guessHandledClass(ContainerBuilder $container, string $serviceId): string

0 commit comments

Comments
 (0)