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

Skip to content

Commit a271c39

Browse files
committed
[Messenger] Add a command to setup transports
1 parent 59f20ad commit a271c39

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
@@ -86,6 +86,13 @@
8686
<tag name="console.command" command="messenger:consume-messages" />
8787
</service>
8888

89+
<service id="console.command.messenger_setup_transports" class="Symfony\Component\Messenger\Command\SetupTransportsCommand">
90+
<argument type="service" id="messenger.receiver_locator" />
91+
<argument type="collection" /> <!-- Receiver names -->
92+
93+
<tag name="console.command" command="messenger:setup-transports" />
94+
</service>
95+
8996
<service id="console.command.messenger_debug" class="Symfony\Component\Messenger\Command\DebugCommand">
9097
<argument type="collection" /> <!-- Message to handlers mapping -->
9198
<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
@@ -19,6 +19,8 @@ CHANGELOG
1919
and queues by default. Previously, this was done when in "debug" mode
2020
only. Pass the `auto-setup` connection option to control this.
2121

22+
* Added a `SetupTransportsCommand` command to setup the transports
23+
2224
4.2.0
2325
-----
2426

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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 $receiverLocator;
30+
private $receiverNames;
31+
32+
public function __construct(ContainerInterface $receiverLocator, array $receiverNames = [])
33+
{
34+
$this->receiverLocator = $receiverLocator;
35+
$this->receiverNames = $receiverNames;
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+
$receiverNames = $this->receiverNames;
62+
// do we want to setup only one receiver?
63+
if ($transport = $input->getArgument('transport')) {
64+
$receiverNames = [$transport];
65+
}
66+
67+
foreach ($receiverNames as $id => $receiverName) {
68+
if (!$this->receiverLocator->has($receiverName)) {
69+
$io->error(sprintf('The "%s" transport does not exist.', $receiverName));
70+
continue;
71+
}
72+
$receiver = $this->receiverLocator->get($receiverName);
73+
if ($receiver instanceof SetupableTransportInterface) {
74+
$receiver->setup();
75+
$io->success(sprintf('The "%s" transport was setup successfully.', $receiverName));
76+
} else {
77+
$io->note(sprintf('The "%s" transport does not support setup.', $receiverName));
78+
}
79+
}
80+
}
81+
}

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);
@@ -252,6 +252,11 @@ private function registerReceivers(ContainerBuilder $container, array $busIds)
252252
->replaceArgument(4, $busIds);
253253
}
254254

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

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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+
/**
23+
* @author Vincent Touzet <[email protected]>
24+
*/
25+
class SetupTransportsCommandTest extends TestCase
26+
{
27+
public function testReceiverNames()
28+
{
29+
// mock a service locator
30+
/** @var MockObject|ServiceLocator $serviceLocator */
31+
$serviceLocator = $this->createMock(ServiceLocator::class);
32+
// get method must be call twice and will return consecutively a setup-able transport and a non setup-able transport
33+
$serviceLocator->expects($this->exactly(2))
34+
->method('get')
35+
->will($this->onConsecutiveCalls(
36+
$this->createMock(SetupableTransportInterface::class),
37+
$this->createMock(TransportInterface::class)
38+
));
39+
$serviceLocator->expects($this->exactly(2))
40+
->method('has')
41+
->willReturn(true);
42+
43+
$command = new SetupTransportsCommand($serviceLocator, ['amqp', 'other_transport']);
44+
$tester = new CommandTester($command);
45+
$tester->execute([]);
46+
$display = $tester->getDisplay();
47+
48+
$this->assertContains('The "amqp" transport was setup successfully.', $display);
49+
$this->assertContains('The "other_transport" transport does not support setup.', $display);
50+
}
51+
52+
public function testReceiverNameArgument()
53+
{
54+
// mock a service locator
55+
/** @var MockObject|ServiceLocator $serviceLocator */
56+
$serviceLocator = $this->createMock(ServiceLocator::class);
57+
// get method must be call twice and will return consecutively a setup-able transport and a non setup-able transport
58+
$serviceLocator->expects($this->exactly(1))
59+
->method('get')
60+
->will($this->onConsecutiveCalls(
61+
$this->createMock(SetupableTransportInterface::class)
62+
));
63+
$serviceLocator->expects($this->exactly(1))
64+
->method('has')
65+
->willReturn(true);
66+
67+
$command = new SetupTransportsCommand($serviceLocator, ['amqp', 'other_transport']);
68+
$tester = new CommandTester($command);
69+
$tester->execute(['transport' => 'amqp']);
70+
$display = $tester->getDisplay();
71+
72+
$this->assertContains('The "amqp" transport was setup successfully.', $display);
73+
}
74+
75+
public function testReceiverNameArgumentNotFound()
76+
{
77+
// mock a service locator
78+
/** @var MockObject|ServiceLocator $serviceLocator */
79+
$serviceLocator = $this->createMock(ServiceLocator::class);
80+
// get method must be call twice and will return consecutively a setup-able transport and a non setup-able transport
81+
$serviceLocator->expects($this->exactly(0))
82+
->method('get');
83+
$serviceLocator->expects($this->exactly(1))
84+
->method('has')
85+
->willReturn(false);
86+
87+
$command = new SetupTransportsCommand($serviceLocator, ['amqp', 'other_transport']);
88+
$tester = new CommandTester($command);
89+
$tester->execute(['transport' => 'not_found']);
90+
$display = $tester->getDisplay();
91+
92+
$this->assertContains('The "not_found" transport does not exist.', $display);
93+
}
94+
}

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(['message_bus'], $container->getDefinition('console.command.messenger_consume_messages')->getArgument(4));
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;
@@ -58,6 +59,14 @@ public function send(Envelope $envelope): Envelope
5859
return ($this->sender ?? $this->getSender())->send($envelope);
5960
}
6061

62+
/**
63+
* {@inheritdoc}
64+
*/
65+
public function setup(): void
66+
{
67+
$this->connection->setup();
68+
}
69+
6170
private function getReceiver()
6271
{
6372
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)