diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
index 7058a3fb2573f..a653e06523aa0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
@@ -9,6 +9,7 @@ CHANGELOG
* Make the `config/` directory optional in `MicroKernelTrait`, add support for service arguments in the
invokable Kernel class, and register `FrameworkBundle` by default when the `bundles.php` file is missing
* [BC BREAK] The `secrets:decrypt-to-local` command terminates with a non-zero exit code when a secret could not be read
+ * Add `priority` option to the `messenger.transports` configurations and pass the configured priority to the `messenger.receiver` service tag
7.1
---
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index d5137dc2ba805..47e03b1f4c52a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -1612,6 +1612,7 @@ function ($a) {
->defaultNull()
->info('Rate limiter name to use when processing messages')
->end()
+ ->integerNode('priority')->defaultValue(0)->info('Priority of this transport when the consumer is executed with the --all flag')->end()
->end()
->end()
->end()
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index ac4c211147a7a..10fb02ec72a49 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -2220,6 +2220,7 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder
->addTag('messenger.receiver', [
'alias' => $name,
'is_failure_transport' => \in_array($name, $failureTransports, true),
+ 'priority' => $transport['priority'],
])
;
$container->setDefinition($transportId = 'messenger.transport.'.$name, $transportDefinition);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
index d8d23168d1887..ec11b30ff3dfa 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -606,6 +606,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php
index bba32ce0b9d1f..8eac58da11fbb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php
@@ -25,6 +25,10 @@
],
'rate_limiter' => 'customised_worker'
],
+ 'prioritized' => [
+ 'dsn' => 'amqp://localhost/%2f/messages?exchange_name=priority',
+ 'priority' => 10,
+ ],
'failed' => 'in-memory:///',
'redis' => 'redis://127.0.0.1:6379/messages',
'beanstalkd' => 'beanstalkd://127.0.0.1:11300',
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml
index b4247360109f1..25f8dbf773ed7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml
@@ -20,6 +20,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml
index 6fb095a3efb1d..a32aa5c16d7fb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml
@@ -23,6 +23,9 @@ framework:
multiplier: 3
max_delay: 100
rate_limiter: customised_worker
+ prioritized:
+ dsn: amqp://localhost/%2f/messages?exchange_name=priority
+ priority: 10
failed: 'in-memory:///'
redis: 'redis://127.0.0.1:6379/messages'
beanstalkd: 'beanstalkd://127.0.0.1:11300'
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php
index b37d2e910ec45..90e76d26cedb4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php
@@ -873,6 +873,7 @@ public function testMessengerMultipleFailureTransports()
$this->assertEquals([
'alias' => 'failure_transport_1',
'is_failure_transport' => true,
+ 'priority' => 0,
], $failureTransport1Tags);
$failureTransport3Definition = $container->getDefinition('messenger.transport.failure_transport_3');
@@ -881,6 +882,7 @@ public function testMessengerMultipleFailureTransports()
$this->assertEquals([
'alias' => 'failure_transport_3',
'is_failure_transport' => true,
+ 'priority' => 0,
], $failureTransport3Tags);
// transport 2 exists but does not appear in the mapping
@@ -913,6 +915,7 @@ public function testMessengerMultipleFailureTransportsWithGlobalFailureTransport
$this->assertEquals([
'alias' => 'failure_transport_1',
'is_failure_transport' => true,
+ 'priority' => 0,
], $failureTransport1Tags);
$failureTransport3Definition = $container->getDefinition('messenger.transport.failure_transport_3');
@@ -921,6 +924,7 @@ public function testMessengerMultipleFailureTransportsWithGlobalFailureTransport
$this->assertEquals([
'alias' => 'failure_transport_3',
'is_failure_transport' => true,
+ 'priority' => 0,
], $failureTransport3Tags);
$failureTransportsByTransportNameServiceLocator = $container->getDefinition('messenger.failure.send_failed_message_to_failure_transport_listener')->getArgument(0);
@@ -947,8 +951,11 @@ public function testMessengerTransports()
$container = $this->createContainerFromFile('messenger_transports');
$this->assertTrue($container->hasDefinition('messenger.transport.default'));
$this->assertTrue($container->getDefinition('messenger.transport.default')->hasTag('messenger.receiver'));
- $this->assertEquals([
- ['alias' => 'default', 'is_failure_transport' => false], ], $container->getDefinition('messenger.transport.default')->getTag('messenger.receiver'));
+ $this->assertEquals([[
+ 'alias' => 'default',
+ 'is_failure_transport' => false,
+ 'priority' => 0,
+ ]], $container->getDefinition('messenger.transport.default')->getTag('messenger.receiver'));
$transportArguments = $container->getDefinition('messenger.transport.default')->getArguments();
$this->assertEquals(new Reference('messenger.default_serializer'), $transportArguments[2]);
@@ -956,6 +963,14 @@ public function testMessengerTransports()
$transportFactory = $container->getDefinition('messenger.transport.customised')->getFactory();
$transportArguments = $container->getDefinition('messenger.transport.customised')->getArguments();
+ $this->assertTrue($container->hasDefinition('messenger.transport.prioritized'));
+ $this->assertTrue($container->getDefinition('messenger.transport.prioritized')->hasTag('messenger.receiver'));
+ $this->assertEquals([[
+ 'alias' => 'prioritized',
+ 'is_failure_transport' => false,
+ 'priority' => 10,
+ ]], $container->getDefinition('messenger.transport.prioritized')->getTag('messenger.receiver'));
+
$this->assertEquals([new Reference('messenger.transport_factory'), 'createTransport'], $transportFactory);
$this->assertCount(3, $transportArguments);
$this->assertSame('amqp://localhost/%2f/messages?exchange_name=exchange_name', $transportArguments[0]);
@@ -1000,6 +1015,7 @@ public function testMessengerTransports()
$failureTransportsByTransportNameServiceLocator = $container->getDefinition('messenger.failure.send_failed_message_to_failure_transport_listener')->getArgument(0);
$failureTransports = $container->getDefinition((string) $failureTransportsByTransportNameServiceLocator)->getArgument(0);
$expectedTransportsByFailureTransports = [
+ 'prioritized' => new Reference('messenger.transport.failed'),
'beanstalkd' => new Reference('messenger.transport.failed'),
'customised' => new Reference('messenger.transport.failed'),
'default' => new Reference('messenger.transport.failed'),
diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md
index e26ef63d0ab17..e8e4f897f6200 100644
--- a/src/Symfony/Component/Messenger/CHANGELOG.md
+++ b/src/Symfony/Component/Messenger/CHANGELOG.md
@@ -7,6 +7,7 @@ CHANGELOG
* `WrappedExceptionsInterface` now extends PHP's `Throwable` interface
* Add `#[AsMessage]` attribute with `$transport` parameter for message routing
* Add `--format` option to the `messenger:stats` command
+ * Allow prioritizing receivers so that `messenger:consume --all` consumes receivers in a predefined order
7.1
---
diff --git a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php
index 9bb32d661ac72..67fccc3189ff0 100644
--- a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php
+++ b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php
@@ -242,6 +242,8 @@ private function registerReceivers(ContainerBuilder $container, array $busIds):
{
$receiverMapping = [];
$failureTransportsMap = [];
+ $receiverPriority = [];
+
if ($container->hasDefinition('console.command.messenger_failed_messages_retry')) {
$commandDefinition = $container->getDefinition('console.command.messenger_failed_messages_retry');
$globalReceiverName = $commandDefinition->getArgument(0);
@@ -263,8 +265,12 @@ private function registerReceivers(ContainerBuilder $container, array $busIds):
$receiverMapping[$id] = new Reference($id);
foreach ($tags as $tag) {
+ $receiverPriority[$id] = max($tag['priority'] ?? 0, $receiverPriority[$id] ?? PHP_INT_MIN);
+
if (isset($tag['alias'])) {
$receiverMapping[$tag['alias']] = $receiverMapping[$id];
+ $receiverPriority[$tag['alias']] = max($tag['priority'] ?? 0, $receiverPriority[$tag['alias']] ?? PHP_INT_MIN);
+
if ($tag['is_failure_transport'] ?? false) {
$failureTransportsMap[$tag['alias']] = $receiverMapping[$id];
}
@@ -272,6 +278,10 @@ private function registerReceivers(ContainerBuilder $container, array $busIds):
}
}
+ $prioritySorter = fn (string $a, string $b): int => $receiverPriority[$b] <=> $receiverPriority[$a];
+ uksort($receiverMapping, $prioritySorter);
+ uksort($failureTransportsMap, $prioritySorter);
+
$receiverNames = [];
foreach ($receiverMapping as $name => $reference) {
$receiverNames[(string) $reference] = $name;
diff --git a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php
index f830489634a11..51894b50aa7b5 100644
--- a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php
+++ b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php
@@ -24,6 +24,7 @@
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpReceiver;
+use Symfony\Component\Messenger\Bridge\Doctrine\Transport\DoctrineReceiver;
use Symfony\Component\Messenger\Command\ConsumeMessagesCommand;
use Symfony\Component\Messenger\Command\DebugCommand;
use Symfony\Component\Messenger\Command\FailedMessagesRetryCommand;
@@ -448,11 +449,12 @@ public function testItRegistersMultipleReceiversAndSetsTheReceiverNamesOnTheComm
]);
$container->register(AmqpReceiver::class, AmqpReceiver::class)->addTag('messenger.receiver', ['alias' => 'amqp']);
+ $container->register(DoctrineReceiver::class, DoctrineReceiver::class)->addTag('messenger.receiver', ['alias' => 'doctrine', 'priority' => 1]);
$container->register(DummyReceiver::class, DummyReceiver::class)->addTag('messenger.receiver', ['alias' => 'dummy']);
(new MessengerPass())->process($container);
- $this->assertSame(['amqp', 'dummy'], $container->getDefinition('console.command.messenger_consume_messages')->getArgument(4));
+ $this->assertSame(['doctrine', 'amqp', 'dummy'], $container->getDefinition('console.command.messenger_consume_messages')->getArgument(4));
}
public function testItSetsTheReceiverNamesOnTheSetupTransportsCommand()
@@ -464,11 +466,12 @@ public function testItSetsTheReceiverNamesOnTheSetupTransportsCommand()
]);
$container->register(AmqpReceiver::class, AmqpReceiver::class)->addTag('messenger.receiver', ['alias' => 'amqp']);
+ $container->register(DoctrineReceiver::class, DoctrineReceiver::class)->addTag('messenger.receiver', ['alias' => 'doctrine', 'priority' => 1]);
$container->register(DummyReceiver::class, DummyReceiver::class)->addTag('messenger.receiver', ['alias' => 'dummy']);
(new MessengerPass())->process($container);
- $this->assertSame(['amqp', 'dummy'], $container->getDefinition('console.command.messenger_setup_transports')->getArgument(1));
+ $this->assertSame(['doctrine', 'amqp', 'dummy'], $container->getDefinition('console.command.messenger_setup_transports')->getArgument(1));
}
public function testItRegistersHandlersOnDifferentBuses()