Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5eb0349

Browse files
committed
feature #26864 [Messenger] Define multiple buses from the framework.messenger.buses configuration (sroze)
This PR was squashed before being merged into the 4.1-dev branch (closes #26864). Discussion ---------- [Messenger] Define multiple buses from the `framework.messenger.buses` configuration | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #26652 | License | MIT | Doc PR | symfony/symfony-docs#9617 Not everybody will benefit from having only one bus, especially with the CQRS-like usages. While keeping the extremely use of use of the single bus, this PR has the following: - Create multiple buses from the YAML configuration - Tag middleware only a specific buses - Register middlewares from the YAML configuration Even if it's visible in the PR's tests, here's how it will look like, for a completely full-customised version: ```yaml framework: messenger: default_bus: commands buses: commands: ~ events: middlewares: - validation - route_messages - "Your\\Middleware\\Service" - call_message_handler ``` A few things to note: 1. The YAML configuration creates `messenger.bus.[name]` services for the buses. 2. The YAML configuration for middleware just adds tags to the corresponding middlewares. 3. If the middleware definition does not exists, it creates it. (without any magic on the arguments though, if it isn't auto-wirable, well... "your problem") 4. In the PR, there is this "TolerateNoHandler" middleware that is a great example for event buses Commits ------- e5deb8499b [Messenger] Define multiple buses from the `framework.messenger.buses` configuration
2 parents a0760db + 9c15c85 commit 5eb0349

15 files changed

+154
-136
lines changed

DependencyInjection/Configuration.php

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,7 @@ private function addMessengerSection(ArrayNodeDefinition $rootNode)
972972
->info('Messenger configuration')
973973
->{!class_exists(FullStack::class) && interface_exists(MessageBusInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}()
974974
->fixXmlConfig('adapter')
975+
->fixXmlConfig('bus', 'buses')
975976
->children()
976977
->arrayNode('routing')
977978
->useAttributeAsKey('message_class')
@@ -1023,14 +1024,6 @@ function ($a) {
10231024
->end()
10241025
->scalarNode('encoder')->defaultValue('messenger.transport.serializer')->end()
10251026
->scalarNode('decoder')->defaultValue('messenger.transport.serializer')->end()
1026-
->arrayNode('middlewares')
1027-
->addDefaultsIfNotSet()
1028-
->children()
1029-
->arrayNode('validation')
1030-
->{!class_exists(FullStack::class) && class_exists(Validation::class) ? 'canBeDisabled' : 'canBeEnabled'}()
1031-
->end()
1032-
->end()
1033-
->end()
10341027
->arrayNode('adapters')
10351028
->useAttributeAsKey('name')
10361029
->arrayPrototype()
@@ -1052,6 +1045,22 @@ function ($a) {
10521045
->end()
10531046
->end()
10541047
->end()
1048+
->scalarNode('default_bus')->defaultValue(null)->end()
1049+
->arrayNode('buses')
1050+
->defaultValue(array('default' => array('default_middlewares' => true, 'middlewares' => array())))
1051+
->useAttributeAsKey('name')
1052+
->prototype('array')
1053+
->fixXmlConfig('middleware')
1054+
->addDefaultsIfNotSet()
1055+
->children()
1056+
->booleanNode('default_middlewares')->defaultTrue()->end()
1057+
->arrayNode('middlewares')
1058+
->defaultValue(array())
1059+
->prototype('scalar')->end()
1060+
->end()
1061+
->end()
1062+
->end()
1063+
->end()
10551064
->end()
10561065
->end()
10571066
->end()

DependencyInjection/FrameworkExtension.php

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
use Symfony\Component\Lock\Store\StoreFactory;
6262
use Symfony\Component\Lock\StoreInterface;
6363
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
64+
use Symfony\Component\Messenger\MessageBus;
6465
use Symfony\Component\Messenger\MessageBusInterface;
6566
use Symfony\Component\Messenger\Transport\ReceiverInterface;
6667
use Symfony\Component\Messenger\Transport\SenderInterface;
@@ -273,7 +274,7 @@ public function load(array $configs, ContainerBuilder $container)
273274
}
274275

275276
if ($this->isConfigEnabled($container, $config['messenger'])) {
276-
$this->registerMessengerConfiguration($config['messenger'], $container, $loader, $config['serializer']);
277+
$this->registerMessengerConfiguration($config['messenger'], $container, $loader, $config['serializer'], $config['validation']);
277278
} else {
278279
$container->removeDefinition('console.command.messenger_consume_messages');
279280
}
@@ -1439,7 +1440,7 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont
14391440
}
14401441
}
14411442

1442-
private function registerMessengerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader, array $serializerConfig)
1443+
private function registerMessengerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader, array $serializerConfig, array $validationConfig)
14431444
{
14441445
if (!interface_exists(MessageBusInterface::class)) {
14451446
throw new LogicException('Messenger support cannot be enabled as the Messenger component is not installed.');
@@ -1462,21 +1463,44 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder
14621463
$container->setAlias('messenger.transport.encoder', $config['encoder']);
14631464
$container->setAlias('messenger.transport.decoder', $config['decoder']);
14641465

1465-
$messageToSenderIdsMapping = array();
1466-
foreach ($config['routing'] as $message => $messageConfiguration) {
1467-
$messageToSenderIdsMapping[$message] = $messageConfiguration['senders'];
1466+
if (null === $config['default_bus']) {
1467+
if (count($config['buses']) > 1) {
1468+
throw new LogicException(sprintf('You need to define a default bus with the "default_bus" configuration. Possible values: %s', implode(', ', array_keys($config['buses']))));
1469+
}
1470+
1471+
$config['default_bus'] = array_keys($config['buses'])[0];
14681472
}
14691473

1470-
$container->getDefinition('messenger.asynchronous.routing.sender_locator')->replaceArgument(1, $messageToSenderIdsMapping);
1474+
$defaultMiddlewares = array('before' => array('logging'), 'after' => array('route_messages', 'call_message_handler'));
1475+
foreach ($config['buses'] as $name => $bus) {
1476+
$busId = 'messenger.bus.'.$name;
1477+
1478+
$middlewares = $bus['default_middlewares'] ? array_merge($defaultMiddlewares['before'], $bus['middlewares'], $defaultMiddlewares['after']) : $bus['middlewares'];
14711479

1472-
if ($config['middlewares']['validation']['enabled']) {
1473-
if (!$container->has('validator')) {
1480+
if (in_array('messenger.middleware.validation', $middlewares) && !$validationConfig['enabled']) {
14741481
throw new LogicException('The Validation middleware is only available when the Validator component is installed and enabled. Try running "composer require symfony/validator".');
14751482
}
1476-
} else {
1477-
$container->removeDefinition('messenger.middleware.validator');
1483+
1484+
$container->setParameter($busId.'.middlewares', $middlewares);
1485+
$container->setDefinition($busId, (new Definition(MessageBus::class, array(array())))->addTag('messenger.bus', array('name' => $name)));
1486+
1487+
if ($name === $config['default_bus']) {
1488+
$container->setAlias('message_bus', $busId);
1489+
$container->setAlias(MessageBusInterface::class, $busId);
1490+
}
1491+
}
1492+
1493+
if (!$container->hasAlias('message_bus')) {
1494+
throw new LogicException(sprintf('The default bus named "%s" is not defined. Define it or change the default bus name.', $config['default_bus']));
1495+
}
1496+
1497+
$messageToSenderIdsMapping = array();
1498+
foreach ($config['routing'] as $message => $messageConfiguration) {
1499+
$messageToSenderIdsMapping[$message] = $messageConfiguration['senders'];
14781500
}
14791501

1502+
$container->getDefinition('messenger.asynchronous.routing.sender_locator')->replaceArgument(1, $messageToSenderIdsMapping);
1503+
14801504
foreach ($config['adapters'] as $name => $adapter) {
14811505
$container->setDefinition('messenger.sender.'.$name, (new Definition(SenderInterface::class))->setFactory(array(
14821506
new Reference('messenger.adapter_factory'),

Resources/config/messenger.xml

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,18 @@
77
<services>
88
<defaults public="false" />
99

10-
<!-- Bus -->
11-
<service id="message_bus" class="Symfony\Component\Messenger\MessageBus" public="true">
12-
<argument type="tagged" tag="messenger.bus_middleware" /> <!-- Middlewares -->
13-
</service>
14-
15-
<service id="Symfony\Component\Messenger\MessageBusInterface" alias="message_bus" />
16-
1710
<!-- Handlers -->
1811
<service id="messenger.handler_resolver" class="Symfony\Component\Messenger\ContainerHandlerLocator">
1912
<argument type="service" id="service_container"/>
2013
</service>
2114

22-
<service id="messenger.middleware.call_message_handler" class="Symfony\Component\Messenger\Middleware\HandleMessageMiddleware">
23-
<argument type="service" id="messenger.handler_resolver" />
24-
25-
<tag name="messenger.bus_middleware" priority="-10" />
26-
</service>
27-
28-
<service id="messenger.middleware.validator" class="Symfony\Component\Messenger\Middleware\ValidationMiddleware">
29-
<argument type="service" id="validator" />
30-
31-
<tag name="messenger.bus_middleware" priority="100" />
32-
</service>
33-
3415
<!-- Asynchronous -->
3516
<service id="messenger.asynchronous.routing.sender_locator" class="Symfony\Component\Messenger\Asynchronous\Routing\SenderLocator">
3617
<argument type="service" id="messenger.sender_locator" />
3718
<argument /> <!-- Message to sender ID mapping -->
3819
</service>
39-
<service id="messenger.asynchronous.middleware.send_message_to_producer" class="Symfony\Component\Messenger\Asynchronous\Middleware\SendMessageMiddleware">
20+
<service id="messenger.middleware.route_messages" class="Symfony\Component\Messenger\Asynchronous\Middleware\SendMessageMiddleware">
4021
<argument type="service" id="messenger.asynchronous.routing.sender_locator" />
41-
42-
<tag name="messenger.bus_middleware" priority="-5" />
4322
</service>
4423

4524
<!-- Message encoding/decoding -->
@@ -49,17 +28,25 @@
4928
<argument type="collection" /> <!-- Context -->
5029
</service>
5130

31+
<!-- Middlewares -->
32+
<service id="messenger.middleware.tolerate_no_handler" class="Symfony\Component\Messenger\Middleware\TolerateNoHandler" abstract="true" />
33+
<service id="messenger.middleware.call_message_handler" class="Symfony\Component\Messenger\Middleware\HandleMessageMiddleware" abstract="true">
34+
<argument type="service" id="messenger.handler_resolver" />
35+
</service>
36+
37+
<service id="messenger.middleware.validation" class="Symfony\Component\Messenger\Middleware\ValidationMiddleware" abstract="true">
38+
<argument type="service" id="validator" />
39+
</service>
40+
5241
<!-- Logging & Debug -->
53-
<service id="messenger.middleware.debug.logging" class="Symfony\Component\Messenger\Debug\LoggingMiddleware">
42+
<service id="messenger.middleware.logging" class="Symfony\Component\Messenger\Middleware\LoggingMiddleware" abstract="true">
5443
<argument type="service" id="logger" />
5544

56-
<tag name="messenger.bus_middleware" priority="10" />
5745
<tag name="monolog.logger" channel="messenger" />
5846
</service>
5947

60-
<service id="data_collector.messenger" class="Symfony\Component\Messenger\DataCollector\MessengerDataCollector">
48+
<service id="messenger.data_collector" class="Symfony\Component\Messenger\DataCollector\MessengerDataCollector">
6149
<tag name="data_collector" template="@WebProfiler/Collector/messenger.html.twig" id="messenger" priority="100" />
62-
<tag name="messenger.bus_middleware" />
6350
</service>
6451

6552
<!-- Discovery -->

Resources/config/schema/symfony-1.0.xsd

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,10 @@
356356
<xsd:element name="encoder" type="xsd:string" minOccurs="0" />
357357
<xsd:element name="decoder" type="xsd:string" minOccurs="0" />
358358
<xsd:element name="routing" type="messenger_routing" minOccurs="0" maxOccurs="unbounded" />
359-
<xsd:element name="middlewares" type="messenger_middleware" minOccurs="0" maxOccurs="unbounded" />
360359
<xsd:element name="adapter" type="messenger_adapter" minOccurs="0" maxOccurs="unbounded" />
360+
<xsd:element name="bus" type="messenger_bus" minOccurs="0" maxOccurs="unbounded" />
361361
</xsd:sequence>
362+
<xsd:attribute name="default-bus" type="xsd:string" />
362363
</xsd:complexType>
363364

364365
<xsd:complexType name="messenger_serializer">
@@ -388,13 +389,16 @@
388389
<xsd:attribute name="dsn" type="xsd:string" />
389390
</xsd:complexType>
390391

391-
<xsd:complexType name="messenger_middleware">
392-
<xsd:sequence>
393-
<xsd:element name="validation" type="messenger_validation" minOccurs="0" maxOccurs="1" />
394-
</xsd:sequence>
392+
<xsd:complexType name="messenger_adapter_option">
393+
<xsd:attribute name="name" type="xsd:string" />
394+
<xsd:attribute name="value" type="xsd:string" />
395395
</xsd:complexType>
396396

397-
<xsd:complexType name="messenger_validation">
398-
<xsd:attribute name="enabled" type="xsd:boolean" />
397+
<xsd:complexType name="messenger_bus">
398+
<xsd:sequence>
399+
<xsd:element name="middleware" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
400+
</xsd:sequence>
401+
<xsd:attribute name="name" type="xsd:string" use="required"/>
402+
<xsd:attribute name="default-middlewares" type="xsd:boolean"/>
399403
</xsd:complexType>
400404
</xsd:schema>

Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,6 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor
254254
'messenger' => array(
255255
'enabled' => !class_exists(FullStack::class) && interface_exists(MessageBusInterface::class),
256256
'routing' => array(),
257-
'middlewares' => array(
258-
'validation' => array(
259-
'enabled' => !class_exists(FullStack::class),
260-
),
261-
),
262257
'adapters' => array(),
263258
'serializer' => array(
264259
'enabled' => true,
@@ -267,6 +262,8 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor
267262
),
268263
'encoder' => 'messenger.transport.serializer',
269264
'decoder' => 'messenger.transport.serializer',
265+
'default_bus' => null,
266+
'buses' => array('default' => array('default_middlewares' => true, 'middlewares' => array())),
270267
),
271268
);
272269
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
$container->loadFromExtension('framework', array(
4+
'messenger' => array(
5+
'default_bus' => 'commands',
6+
'buses' => array(
7+
'commands' => null,
8+
'events' => array(
9+
'middlewares' => array(
10+
'tolerate_no_handler',
11+
),
12+
),
13+
'queries' => array(
14+
'default_middlewares' => false,
15+
'middlewares' => array(
16+
'route_messages',
17+
'tolerate_no_handler',
18+
'call_message_handler',
19+
),
20+
),
21+
),
22+
),
23+
));

Tests/DependencyInjection/Fixtures/php/messenger_validation_disabled.php

Lines changed: 0 additions & 11 deletions
This file was deleted.

Tests/DependencyInjection/Fixtures/php/messenger_validation_enabled.php

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<container xmlns="http://symfony.com/schema/dic/services"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:framework="http://symfony.com/schema/dic/symfony"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
6+
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
7+
8+
<framework:config>
9+
<framework:messenger default-bus="commands">
10+
<framework:bus name="commands" />
11+
<framework:bus name="events">
12+
<framework:middleware>tolerate_no_handler</framework:middleware>
13+
</framework:bus>
14+
<framework:bus name="queries" default-middlewares="false">
15+
<framework:middleware>route_messages</framework:middleware>
16+
<framework:middleware>tolerate_no_handler</framework:middleware>
17+
<framework:middleware>call_message_handler</framework:middleware>
18+
</framework:bus>
19+
</framework:messenger>
20+
</framework:config>
21+
</container>

Tests/DependencyInjection/Fixtures/xml/messenger_validation_disabled.xml

Lines changed: 0 additions & 15 deletions
This file was deleted.

Tests/DependencyInjection/Fixtures/xml/messenger_validation_enabled.xml

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
framework:
2+
messenger:
3+
default_bus: commands
4+
buses:
5+
commands: ~
6+
events:
7+
middlewares:
8+
- "tolerate_no_handler"
9+
queries:
10+
default_middlewares: false
11+
middlewares:
12+
- "route_messages"
13+
- "tolerate_no_handler"
14+
- "call_message_handler"

Tests/DependencyInjection/Fixtures/yml/messenger_validation_disabled.yml

Lines changed: 0 additions & 5 deletions
This file was deleted.

Tests/DependencyInjection/Fixtures/yml/messenger_validation_enabled.yml

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)