Skip to content

Commit eafe882

Browse files
author
scyzoryck
committed
[Messenger] Add completion for failed messages commands.
1 parent 85bf403 commit eafe882

7 files changed

+269
-4
lines changed

.php-cs-fixer.dist.php

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
->notPath('Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Custom/_name_entry_label.html.php')
4242
// explicit trigger_error tests
4343
->notPath('Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php')
44+
// stop removing spaces on the end of the line in strings
45+
->notPath('Symfony/Component/Messenger/Tests/Command/FailedMessagesShowCommandTest.php')
4446
)
4547
->setCacheFile('.php-cs-fixer.cache')
4648
;

src/Symfony/Component/Messenger/Command/AbstractFailedMessagesCommand.php

+28
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\Component\Messenger\Command;
1313

1414
use Symfony\Component\Console\Command\Command;
15+
use Symfony\Component\Console\Completion\CompletionInput;
16+
use Symfony\Component\Console\Completion\CompletionSuggestions;
1517
use Symfony\Component\Console\Helper\Dumper;
1618
use Symfony\Component\Console\Question\ChoiceQuestion;
1719
use Symfony\Component\Console\Style\SymfonyStyle;
@@ -23,6 +25,7 @@
2325
use Symfony\Component\Messenger\Stamp\RedeliveryStamp;
2426
use Symfony\Component\Messenger\Stamp\SentToFailureTransportStamp;
2527
use Symfony\Component\Messenger\Stamp\TransportMessageIdStamp;
28+
use Symfony\Component\Messenger\Transport\Receiver\ListableReceiverInterface;
2629
use Symfony\Component\Messenger\Transport\Receiver\MessageCountAwareInterface;
2730
use Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface;
2831
use Symfony\Component\VarDumper\Caster\Caster;
@@ -263,4 +266,29 @@ protected function interactiveChooseFailureTransport(SymfonyStyle $io)
263266

264267
return $io->askQuestion($question);
265268
}
269+
270+
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
271+
{
272+
if ($input->mustSuggestOptionValuesFor('transport')) {
273+
$suggestions->suggestValues(array_keys($this->failureTransports->getProvidedServices()));
274+
275+
return;
276+
}
277+
278+
if ($input->mustSuggestArgumentValuesFor('id')) {
279+
$transport = $input->getOption('transport');
280+
$receiver = $this->getReceiver($transport);
281+
if (!$receiver instanceof ListableReceiverInterface) {
282+
return;
283+
}
284+
285+
$ids = [];
286+
foreach ($receiver->all(50) as $envelope) {
287+
$ids[] = $this->getMessageId($envelope);
288+
}
289+
$suggestions->suggestValues($ids);
290+
291+
return;
292+
}
293+
}
266294
}

src/Symfony/Component/Messenger/Command/FailedMessagesRetryCommand.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ protected function configure(): void
6161
->setDefinition([
6262
new InputArgument('id', InputArgument::IS_ARRAY, 'Specific message id(s) to retry'),
6363
new InputOption('force', null, InputOption::VALUE_NONE, 'Force action without confirmation'),
64-
new InputOption('transport', null, InputOption::VALUE_OPTIONAL, 'Use a specific failure transport', self::DEFAULT_TRANSPORT_OPTION),
64+
new InputOption('transport', null, InputOption::VALUE_OPTIONAL, 'Use a specific failure transport'),
6565
])
6666
->setDescription(self::$defaultDescription)
6767
->setHelp(<<<'EOF'
@@ -100,9 +100,11 @@ protected function execute(InputInterface $input, OutputInterface $output)
100100
}
101101

102102
$failureTransportName = $input->getOption('transport');
103-
if (self::DEFAULT_TRANSPORT_OPTION === $failureTransportName) {
103+
if (null === $failureTransportName) {
104+
$failureTransportName = $this->getGlobalFailureReceiverName();
104105
$this->printWarningAvailableFailureTransports($io, $this->getGlobalFailureReceiverName());
105106
}
107+
106108
if ('' === $failureTransportName || null === $failureTransportName) {
107109
$failureTransportName = $this->interactiveChooseFailureTransport($io);
108110
}

src/Symfony/Component/Messenger/Command/FailedMessagesShowCommand.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ protected function configure(): void
4141
->setDefinition([
4242
new InputArgument('id', InputArgument::OPTIONAL, 'Specific message id to show'),
4343
new InputOption('max', null, InputOption::VALUE_REQUIRED, 'Maximum number of messages to list', 50),
44-
new InputOption('transport', null, InputOption::VALUE_OPTIONAL, 'Use a specific failure transport', self::DEFAULT_TRANSPORT_OPTION),
44+
new InputOption('transport', null, InputOption::VALUE_OPTIONAL, 'Use a specific failure transport'),
4545
])
4646
->setDescription(self::$defaultDescription)
4747
->setHelp(<<<'EOF'
@@ -65,7 +65,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
6565
$io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
6666

6767
$failureTransportName = $input->getOption('transport');
68-
if (self::DEFAULT_TRANSPORT_OPTION === $failureTransportName) {
68+
if (null === $failureTransportName) {
69+
$failureTransportName = $this->getGlobalFailureReceiverName();
6970
$this->printWarningAvailableFailureTransports($io, $this->getGlobalFailureReceiverName());
7071
}
7172
if ('' === $failureTransportName || null === $failureTransportName) {

src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRemoveCommandTest.php

+76
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
namespace Symfony\Component\Messenger\Tests\Command;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Console\Tester\CommandCompletionTester;
1516
use Symfony\Component\Console\Tester\CommandTester;
1617
use Symfony\Component\DependencyInjection\ServiceLocator;
1718
use Symfony\Component\Messenger\Command\FailedMessagesRemoveCommand;
1819
use Symfony\Component\Messenger\Envelope;
1920
use Symfony\Component\Messenger\Exception\InvalidArgumentException;
21+
use Symfony\Component\Messenger\Stamp\TransportMessageIdStamp;
2022
use Symfony\Component\Messenger\Transport\Receiver\ListableReceiverInterface;
2123

2224
class FailedMessagesRemoveCommandTest extends TestCase
@@ -268,4 +270,78 @@ public function testRemoveMultipleMessagesAndDisplayMessagesWithServiceLocator()
268270
$this->assertStringContainsString('Message with id 20 removed.', $tester->getDisplay());
269271
$this->assertStringContainsString('Message with id 30 removed.', $tester->getDisplay());
270272
}
273+
274+
public function testCompletingTransport()
275+
{
276+
$globalFailureReceiverName = 'failure_receiver';
277+
278+
$receiver = $this->createMock(ListableReceiverInterface::class);
279+
280+
$serviceLocator = $this->createMock(ServiceLocator::class);
281+
$serviceLocator->expects($this->once())->method('getProvidedServices')->willReturn([
282+
'global_receiver' => $receiver,
283+
$globalFailureReceiverName => $receiver,
284+
]);
285+
286+
$command = new FailedMessagesRemoveCommand(
287+
$globalFailureReceiverName,
288+
$serviceLocator
289+
);
290+
$tester = new CommandCompletionTester($command);
291+
292+
$suggestions = $tester->complete(['--transport']);
293+
$this->assertSame(['global_receiver', 'failure_receiver'], $suggestions);
294+
}
295+
296+
public function testCompleteId()
297+
{
298+
$globalFailureReceiverName = 'failure_receiver';
299+
300+
$receiver = $this->createMock(ListableReceiverInterface::class);
301+
$receiver->expects($this->once())->method('all')->with(50)->willReturn([
302+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('2ab50dfa1fbf')]),
303+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('78c2da843723')]),
304+
]);
305+
306+
$serviceLocator = $this->createMock(ServiceLocator::class);
307+
$serviceLocator->expects($this->once())->method('has')->with($globalFailureReceiverName)->willReturn(true);
308+
$serviceLocator->expects($this->any())->method('get')->with($globalFailureReceiverName)->willReturn($receiver);
309+
310+
$command = new FailedMessagesRemoveCommand(
311+
$globalFailureReceiverName,
312+
$serviceLocator
313+
);
314+
$tester = new CommandCompletionTester($command);
315+
316+
$suggestions = $tester->complete(['']);
317+
318+
$this->assertSame(['2ab50dfa1fbf', '78c2da843723'], $suggestions);
319+
}
320+
321+
public function testCompleteIdWithSpecifiedTransport()
322+
{
323+
$globalFailureReceiverName = 'failure_receiver';
324+
$anotherFailureReceiverName = 'another_receiver';
325+
326+
$receiver = $this->createMock(ListableReceiverInterface::class);
327+
$receiver->expects($this->once())->method('all')->with(50)->willReturn([
328+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('2ab50dfa1fbf')]),
329+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('78c2da843723')]),
330+
]);
331+
332+
$serviceLocator = $this->createMock(ServiceLocator::class);
333+
$serviceLocator->expects($this->once())->method('has')->with($anotherFailureReceiverName)->willReturn(true);
334+
$serviceLocator->expects($this->any())->method('get')->with($anotherFailureReceiverName)->willReturn($receiver);
335+
336+
$command = new FailedMessagesRemoveCommand(
337+
$globalFailureReceiverName,
338+
$serviceLocator
339+
);
340+
341+
$tester = new CommandCompletionTester($command);
342+
343+
$suggestions = $tester->complete(['--transport', $anotherFailureReceiverName, ' ']);
344+
345+
$this->assertSame(['2ab50dfa1fbf', '78c2da843723'], $suggestions);
346+
}
271347
}

src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php

+81
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
namespace Symfony\Component\Messenger\Tests\Command;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Console\Tester\CommandCompletionTester;
1516
use Symfony\Component\Console\Tester\CommandTester;
1617
use Symfony\Component\DependencyInjection\ServiceLocator;
1718
use Symfony\Component\EventDispatcher\EventDispatcher;
1819
use Symfony\Component\Messenger\Command\FailedMessagesRetryCommand;
1920
use Symfony\Component\Messenger\Envelope;
2021
use Symfony\Component\Messenger\MessageBusInterface;
22+
use Symfony\Component\Messenger\Stamp\TransportMessageIdStamp;
2123
use Symfony\Component\Messenger\Transport\Receiver\ListableReceiverInterface;
2224

2325
class FailedMessagesRetryCommandTest extends TestCase
@@ -144,4 +146,83 @@ public function testBasicRunWithServiceLocatorWithSpecificFailureTransport()
144146

145147
$this->assertStringContainsString('[OK]', $tester->getDisplay());
146148
}
149+
150+
public function testCompletingTransport()
151+
{
152+
$globalFailureReceiverName = 'failure_receiver';
153+
154+
$receiver = $this->createMock(ListableReceiverInterface::class);
155+
156+
$serviceLocator = $this->createMock(ServiceLocator::class);
157+
$serviceLocator->expects($this->once())->method('getProvidedServices')->willReturn([
158+
'global_receiver' => $receiver,
159+
$globalFailureReceiverName => $receiver,
160+
]);
161+
162+
$command = new FailedMessagesRetryCommand(
163+
$globalFailureReceiverName,
164+
$serviceLocator,
165+
$this->createMock(MessageBusInterface::class),
166+
new EventDispatcher()
167+
);
168+
$tester = new CommandCompletionTester($command);
169+
170+
$suggestions = $tester->complete(['--transport']);
171+
$this->assertSame(['global_receiver', 'failure_receiver'], $suggestions);
172+
}
173+
174+
public function testCompleteId()
175+
{
176+
$globalFailureReceiverName = 'failure_receiver';
177+
178+
$receiver = $this->createMock(ListableReceiverInterface::class);
179+
$receiver->expects($this->once())->method('all')->with(50)->willReturn([
180+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('2ab50dfa1fbf')]),
181+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('78c2da843723')]),
182+
]);
183+
184+
$serviceLocator = $this->createMock(ServiceLocator::class);
185+
$serviceLocator->expects($this->once())->method('has')->with($globalFailureReceiverName)->willReturn(true);
186+
$serviceLocator->expects($this->any())->method('get')->with($globalFailureReceiverName)->willReturn($receiver);
187+
188+
$command = new FailedMessagesRetryCommand(
189+
$globalFailureReceiverName,
190+
$serviceLocator,
191+
$this->createMock(MessageBusInterface::class),
192+
new EventDispatcher()
193+
);
194+
$tester = new CommandCompletionTester($command);
195+
196+
$suggestions = $tester->complete(['']);
197+
198+
$this->assertSame(['2ab50dfa1fbf', '78c2da843723'], $suggestions);
199+
}
200+
201+
public function testCompleteIdWithSpecifiedTransport()
202+
{
203+
$globalFailureReceiverName = 'failure_receiver';
204+
$anotherFailureReceiverName = 'another_receiver';
205+
206+
$receiver = $this->createMock(ListableReceiverInterface::class);
207+
$receiver->expects($this->once())->method('all')->with(50)->willReturn([
208+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('2ab50dfa1fbf')]),
209+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('78c2da843723')]),
210+
]);
211+
212+
$serviceLocator = $this->createMock(ServiceLocator::class);
213+
$serviceLocator->expects($this->once())->method('has')->with($anotherFailureReceiverName)->willReturn(true);
214+
$serviceLocator->expects($this->any())->method('get')->with($anotherFailureReceiverName)->willReturn($receiver);
215+
216+
$command = new FailedMessagesRetryCommand(
217+
$globalFailureReceiverName,
218+
$serviceLocator,
219+
$this->createMock(MessageBusInterface::class),
220+
new EventDispatcher()
221+
);
222+
$tester = new CommandCompletionTester($command);
223+
224+
$suggestions = $tester->complete(['--transport', $anotherFailureReceiverName, ' ']);
225+
226+
$this->assertSame(['2ab50dfa1fbf', '78c2da843723'], $suggestions);
227+
}
147228
}

src/Symfony/Component/Messenger/Tests/Command/FailedMessagesShowCommandTest.php

+75
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Console\Output\OutputInterface;
16+
use Symfony\Component\Console\Tester\CommandCompletionTester;
1617
use Symfony\Component\Console\Tester\CommandTester;
1718
use Symfony\Component\DependencyInjection\ServiceLocator;
1819
use Symfony\Component\Messenger\Command\FailedMessagesShowCommand;
@@ -607,4 +608,78 @@ public function testListMessagesWithServiceLocatorFromSpecificTransport()
607608
$redeliveryStamp->getRedeliveredAt()->format('Y-m-d H:i:s')),
608609
$tester->getDisplay(true));
609610
}
611+
612+
613+
public function testCompletingTransport()
614+
{
615+
$globalFailureReceiverName = 'failure_receiver';
616+
617+
$receiver = $this->createMock(ListableReceiverInterface::class);
618+
619+
$serviceLocator = $this->createMock(ServiceLocator::class);
620+
$serviceLocator->expects($this->once())->method('getProvidedServices')->willReturn([
621+
'global_receiver' => $receiver,
622+
$globalFailureReceiverName => $receiver,
623+
]);
624+
625+
$command = new FailedMessagesShowCommand(
626+
$globalFailureReceiverName,
627+
$serviceLocator
628+
);
629+
$tester = new CommandCompletionTester($command);
630+
631+
$suggestions = $tester->complete(['--transport']);
632+
$this->assertSame(['global_receiver', 'failure_receiver'], $suggestions);
633+
}
634+
635+
public function testCompleteId()
636+
{
637+
$globalFailureReceiverName = 'failure_receiver';
638+
639+
$receiver = $this->createMock(ListableReceiverInterface::class);
640+
$receiver->expects($this->once())->method('all')->with(50)->willReturn([
641+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('2ab50dfa1fbf')]),
642+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('78c2da843723')]),
643+
]);
644+
645+
$serviceLocator = $this->createMock(ServiceLocator::class);
646+
$serviceLocator->expects($this->once())->method('has')->with($globalFailureReceiverName)->willReturn(true);
647+
$serviceLocator->expects($this->any())->method('get')->with($globalFailureReceiverName)->willReturn($receiver);
648+
649+
$command = new FailedMessagesShowCommand(
650+
$globalFailureReceiverName,
651+
$serviceLocator
652+
);
653+
$tester = new CommandCompletionTester($command);
654+
655+
$suggestions = $tester->complete(['']);
656+
657+
$this->assertSame(['2ab50dfa1fbf', '78c2da843723'], $suggestions);
658+
}
659+
660+
public function testCompleteIdWithSpecifiedTransport()
661+
{
662+
$globalFailureReceiverName = 'failure_receiver';
663+
$anotherFailureReceiverName = 'another_receiver';
664+
665+
$receiver = $this->createMock(ListableReceiverInterface::class);
666+
$receiver->expects($this->once())->method('all')->with(50)->willReturn([
667+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('2ab50dfa1fbf')]),
668+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('78c2da843723')]),
669+
]);
670+
671+
$serviceLocator = $this->createMock(ServiceLocator::class);
672+
$serviceLocator->expects($this->once())->method('has')->with($anotherFailureReceiverName)->willReturn(true);
673+
$serviceLocator->expects($this->any())->method('get')->with($anotherFailureReceiverName)->willReturn($receiver);
674+
675+
$command = new FailedMessagesShowCommand(
676+
$globalFailureReceiverName,
677+
$serviceLocator
678+
);
679+
$tester = new CommandCompletionTester($command);
680+
681+
$suggestions = $tester->complete(['--transport', $anotherFailureReceiverName, ' ']);
682+
683+
$this->assertSame(['2ab50dfa1fbf', '78c2da843723'], $suggestions);
684+
}
610685
}

0 commit comments

Comments
 (0)