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

Skip to content

Commit cada294

Browse files
committed
[Messenger] Add a command to setup transports
1 parent aa12dd0 commit cada294

File tree

10 files changed

+245
-5
lines changed

10 files changed

+245
-5
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ CHANGELOG
1919
* Added support for Translator paths, Twig paths in translation commands.
2020
* Added support for PHP files with translations in translation commands.
2121
* Added support for boolean container parameters within routes.
22+
* Added the `messenger:setup-transports` command to setup messenger transports
2223

2324
4.2.0
2425
-----

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ public function load(array $configs, ContainerBuilder $container)
279279
} else {
280280
$container->removeDefinition('console.command.messenger_consume_messages');
281281
$container->removeDefinition('console.command.messenger_debug');
282+
$container->removeDefinition('console.command.messenger_setup_transports');
282283
}
283284

284285
$this->registerValidationConfiguration($config['validation'], $container, $loader);

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@
8989
<tag name="monolog.logger" channel="messenger" />
9090
</service>
9191

92+
<service id="console.command.messenger_setup_transports" class="Symfony\Component\Messenger\Command\SetupTransportsCommand">
93+
<argument type="service" id="messenger.receiver_locator" />
94+
<argument type="collection" /> <!-- Receiver names -->
95+
96+
<tag name="console.command" command="messenger:setup-transports" />
97+
</service>
98+
9299
<service id="console.command.messenger_debug" class="Symfony\Component\Messenger\Command\DebugCommand">
93100
<argument type="collection" /> <!-- Message to handlers mapping -->
94101
<tag name="console.command" command="debug:messenger" />

src/Symfony/Component/Messenger/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ CHANGELOG
5151
and queues by default. Previously, this was done when in "debug" mode
5252
only. Pass the `auto-setup` connection option to control this.
5353

54+
* Added a `SetupTransportsCommand` command to setup the transports
55+
5456
4.2.0
5557
-----
5658

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Messenger\Command;
13+
14+
use Psr\Container\ContainerInterface;
15+
use Symfony\Component\Console\Command\Command;
16+
use Symfony\Component\Console\Input\InputArgument;
17+
use Symfony\Component\Console\Input\InputInterface;
18+
use Symfony\Component\Console\Output\OutputInterface;
19+
use Symfony\Component\Console\Style\SymfonyStyle;
20+
use Symfony\Component\Messenger\Transport\SetupableTransportInterface;
21+
22+
/**
23+
* @author Vincent Touzet <[email protected]>
24+
*/
25+
class SetupTransportsCommand extends Command
26+
{
27+
protected static $defaultName = 'messenger:setup-transports';
28+
29+
private $transportLocator;
30+
private $transportNames;
31+
32+
public function __construct(ContainerInterface $transportLocator, array $transportNames = [])
33+
{
34+
$this->transportLocator = $transportLocator;
35+
$this->transportNames = $transportNames;
36+
37+
parent::__construct();
38+
}
39+
40+
protected function configure()
41+
{
42+
$this
43+
->addArgument('transport', InputArgument::OPTIONAL, 'Name of the transport to setup', null)
44+
->setHelp(<<<EOF
45+
The <info>%command.name%</info> command setups the transports:
46+
47+
<info>php %command.full_name%</info>
48+
49+
Or a specific transport only:
50+
51+
<info>php %command.full_name% <transport></info>
52+
EOF
53+
)
54+
;
55+
}
56+
57+
protected function execute(InputInterface $input, OutputInterface $output)
58+
{
59+
$io = new SymfonyStyle($input, $output);
60+
61+
$transportNames = $this->transportNames;
62+
// do we want to setup only one transport?
63+
if ($transport = $input->getArgument('transport')) {
64+
if (!$this->transportLocator->has($transport)) {
65+
throw new \RuntimeException(sprintf('The "%s" transport does not exist.', $transport));
66+
}
67+
$transportNames = [$transport];
68+
}
69+
70+
foreach ($transportNames as $id => $transportName) {
71+
$transport = $this->transportLocator->get($transportName);
72+
if ($transport instanceof SetupableTransportInterface) {
73+
$transport->setup();
74+
$io->success(sprintf('The "%s" transport was setup successfully.', $transportName));
75+
} else {
76+
$io->note(sprintf('The "%s" transport does not support setup.', $transportName));
77+
}
78+
}
79+
}
80+
}

src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,11 +236,11 @@ private function registerReceivers(ContainerBuilder $container, array $busIds)
236236
}
237237
}
238238

239+
$receiverNames = [];
240+
foreach ($receiverMapping as $name => $reference) {
241+
$receiverNames[(string) $reference] = $name;
242+
}
239243
if ($container->hasDefinition('console.command.messenger_consume_messages')) {
240-
$receiverNames = [];
241-
foreach ($receiverMapping as $name => $reference) {
242-
$receiverNames[(string) $reference] = $name;
243-
}
244244
$buses = [];
245245
foreach ($busIds as $busId) {
246246
$buses[$busId] = new Reference($busId);
@@ -251,6 +251,11 @@ private function registerReceivers(ContainerBuilder $container, array $busIds)
251251
->replaceArgument(3, array_values($receiverNames));
252252
}
253253

254+
if ($container->hasDefinition('console.command.messenger_setup_transports')) {
255+
$container->getDefinition('console.command.messenger_setup_transports')
256+
->replaceArgument(1, array_values($receiverNames));
257+
}
258+
254259
$container->getDefinition('messenger.receiver_locator')->replaceArgument(0, $receiverMapping);
255260
}
256261

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Messenger\Tests\Command;
13+
14+
use PHPUnit\Framework\MockObject\MockObject;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\Component\Console\Tester\CommandTester;
17+
use Symfony\Component\DependencyInjection\ServiceLocator;
18+
use Symfony\Component\Messenger\Command\SetupTransportsCommand;
19+
use Symfony\Component\Messenger\Transport\SetupableTransportInterface;
20+
use Symfony\Component\Messenger\Transport\TransportInterface;
21+
22+
class SetupTransportsCommandTest extends TestCase
23+
{
24+
public function testReceiverNames()
25+
{
26+
// mock a service locator
27+
/** @var MockObject|ServiceLocator $serviceLocator */
28+
$serviceLocator = $this->createMock(ServiceLocator::class);
29+
// get method must be call twice and will return consecutively a setup-able transport and a non setup-able transport
30+
$serviceLocator->expects($this->exactly(2))
31+
->method('get')
32+
->will($this->onConsecutiveCalls(
33+
$this->createMock(SetupableTransportInterface::class),
34+
$this->createMock(TransportInterface::class)
35+
));
36+
$serviceLocator
37+
->method('has')
38+
->willReturn(true);
39+
40+
$command = new SetupTransportsCommand($serviceLocator, ['amqp', 'other_transport']);
41+
$tester = new CommandTester($command);
42+
$tester->execute([]);
43+
$display = $tester->getDisplay();
44+
45+
$this->assertContains('The "amqp" transport was setup successfully.', $display);
46+
$this->assertContains('The "other_transport" transport does not support setup.', $display);
47+
}
48+
49+
public function testReceiverNameArgument()
50+
{
51+
// mock a service locator
52+
/** @var MockObject|ServiceLocator $serviceLocator */
53+
$serviceLocator = $this->createMock(ServiceLocator::class);
54+
// get method must be call twice and will return consecutively a setup-able transport and a non setup-able transport
55+
$serviceLocator->expects($this->exactly(1))
56+
->method('get')
57+
->will($this->onConsecutiveCalls(
58+
$this->createMock(SetupableTransportInterface::class)
59+
));
60+
$serviceLocator->expects($this->exactly(1))
61+
->method('has')
62+
->willReturn(true);
63+
64+
$command = new SetupTransportsCommand($serviceLocator, ['amqp', 'other_transport']);
65+
$tester = new CommandTester($command);
66+
$tester->execute(['transport' => 'amqp']);
67+
$display = $tester->getDisplay();
68+
69+
$this->assertContains('The "amqp" transport was setup successfully.', $display);
70+
}
71+
72+
/**
73+
* @expectedException \RuntimeException
74+
* @expectedExceptionMessage The "not_found" transport does not exist.
75+
*/
76+
public function testReceiverNameArgumentNotFound()
77+
{
78+
// mock a service locator
79+
/** @var MockObject|ServiceLocator $serviceLocator */
80+
$serviceLocator = $this->createMock(ServiceLocator::class);
81+
// get method must be call twice and will return consecutively a setup-able transport and a non setup-able transport
82+
$serviceLocator->expects($this->exactly(0))
83+
->method('get');
84+
$serviceLocator->expects($this->exactly(1))
85+
->method('has')
86+
->willReturn(false);
87+
88+
$command = new SetupTransportsCommand($serviceLocator, ['amqp', 'other_transport']);
89+
$tester = new CommandTester($command);
90+
$tester->execute(['transport' => 'not_found']);
91+
$display = $tester->getDisplay();
92+
93+
$this->assertContains('The "not_found" transport does not exist.', $display);
94+
}
95+
}

src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\DependencyInjection\ServiceLocator;
2121
use Symfony\Component\Messenger\Command\ConsumeMessagesCommand;
2222
use Symfony\Component\Messenger\Command\DebugCommand;
23+
use Symfony\Component\Messenger\Command\SetupTransportsCommand;
2324
use Symfony\Component\Messenger\DataCollector\MessengerDataCollector;
2425
use Symfony\Component\Messenger\DependencyInjection\MessengerPass;
2526
use Symfony\Component\Messenger\Envelope;
@@ -265,6 +266,22 @@ public function testItRegistersMultipleReceiversAndSetsTheReceiverNamesOnTheComm
265266
$this->assertSame(['amqp', 'dummy'], $container->getDefinition('console.command.messenger_consume_messages')->getArgument(3));
266267
}
267268

269+
public function testItSetsTheReceiverNamesOnTheSetupTransportsCommand()
270+
{
271+
$container = $this->getContainerBuilder();
272+
$container->register('console.command.messenger_setup_transports', SetupTransportsCommand::class)->setArguments([
273+
new Reference('messenger.receiver_locator'),
274+
null,
275+
]);
276+
277+
$container->register(AmqpReceiver::class, AmqpReceiver::class)->addTag('messenger.receiver', ['alias' => 'amqp']);
278+
$container->register(DummyReceiver::class, DummyReceiver::class)->addTag('messenger.receiver', ['alias' => 'dummy']);
279+
280+
(new MessengerPass())->process($container);
281+
282+
$this->assertSame(['amqp', 'dummy'], $container->getDefinition('console.command.messenger_setup_transports')->getArgument(1));
283+
}
284+
268285
public function testItShouldNotThrowIfGeneratorIsReturnedInsteadOfArray()
269286
{
270287
$container = $this->getContainerBuilder($busId = 'message_bus');

src/Symfony/Component/Messenger/Transport/AmqpExt/AmqpTransport.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
use Symfony\Component\Messenger\Envelope;
1515
use Symfony\Component\Messenger\Transport\Serialization\PhpSerializer;
1616
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
17+
use Symfony\Component\Messenger\Transport\SetupableTransportInterface;
1718
use Symfony\Component\Messenger\Transport\TransportInterface;
1819

1920
/**
2021
* @author Nicolas Grekas <[email protected]>
2122
*
2223
* @experimental in 4.2
2324
*/
24-
class AmqpTransport implements TransportInterface
25+
class AmqpTransport implements TransportInterface, SetupableTransportInterface
2526
{
2627
private $serializer;
2728
private $connection;
@@ -74,6 +75,14 @@ public function send(Envelope $envelope): Envelope
7475
return ($this->sender ?? $this->getSender())->send($envelope);
7576
}
7677

78+
/**
79+
* {@inheritdoc}
80+
*/
81+
public function setup(): void
82+
{
83+
$this->connection->setup();
84+
}
85+
7786
private function getReceiver()
7887
{
7988
return $this->receiver = new AmqpReceiver($this->connection, $this->serializer);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Messenger\Transport;
13+
14+
/**
15+
* @author Vincent Touzet <[email protected]>
16+
*/
17+
interface SetupableTransportInterface
18+
{
19+
/**
20+
* Setup the transport.
21+
*/
22+
public function setup(): void;
23+
}

0 commit comments

Comments
 (0)