8000 [Messenger] Add the `--all` option to the `messenger:failed:remove` c… · symfony/symfony@f26d36b · GitHub
[go: up one dir, main page]

Skip to content

Commit f26d36b

Browse files
[Messenger] Add the --all option to the messenger:failed:remove command
1 parent 2bac801 commit f26d36b

File tree

3 files changed

+135
-9
lines changed

3 files changed

+135
-9
lines changed

src/Symfony/Component/Messenger/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* Deprecate `StopWorkerOnSignalsListener` in favor of using the `SignalableCommandInterface`
88
* Add `HandlerDescriptor::getOptions`
9+
* Add the `--all` option to the `messenger:failed:remove` command
910

1011
6.3
1112
---

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

+50-7
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212
namespace Symfony\Component\Messenger\Command;
1313

1414
use Symfony\Component\Console\Attribute\AsCommand;
15+
use Symfony\Componen 10000 t\Console\Command\Command;
1516
use Symfony\Component\Console\Exception\RuntimeException;
1617
use Symfony\Component\Console\Input\InputArgument;
1718
use Symfony\Component\Console\Input\InputInterface;
1819
use Symfony\Component\Console\Input\InputOption;
1920
use Symfony\Component\Console\Output\ConsoleOutputInterface;
2021
use Symfony\Component\Console\Output\OutputInterface;
2122
use Symfony\Component\Console\Style\SymfonyStyle;
23+
use Symfony\Component\Messenger\Envelope;
2224
use Symfony\Component\Messenger\Transport\Receiver\ListableReceiverInterface;
2325
use Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface;
2426

@@ -32,7 +34,8 @@ protected function configure(): void
3234
{
3335
$this
3436
->setDefinition([
35-
new InputArgument('id', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'Specific message id(s) to remove'),
37+
new InputArgument('id', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Specific message id(s) to remove'),
38+
new InputOption('all', null, InputOption::VALUE_NONE, 'Remove all failed messages from the transport'),
3639
new InputOption('force', null, InputOption::VALUE_NONE, 'Force the operation without confirmation'),
3740
new InputOption('transport', null, InputOption::VALUE_OPTIONAL, 'Use a specific failure transport', self::DEFAULT_TRANSPORT_OPTION),
3841
new InputOption('show-messages', null, InputOption::VALUE_NONE, 'Display messages before removing it (if multiple ids are given)'),
@@ -43,6 +46,10 @@ protected function configure(): void
4346
<info>php %command.full_name% {id1} [{id2} ...]</info>
4447
4548
The specific ids can be found via the messenger:failed:show command.
49+
50+
You can remove all messages from the failure transport by using the "--all" option (note that you also need the "--force" option):
51+
52+
<info>php %command.full_name% --all --force</info>
4653
EOF
4754
)
4855
;
@@ -61,18 +68,32 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6168

6269
$shouldForce = $input->getOption('force');
6370
$ids = (array) $input->getArgument('id');
64-
$shouldDisplayMessages = $input->getOption('show-messages') || 1 === \count($ids);
65-
$this->removeMessages($failureTransportName, $ids, $receiver, $io, $shouldForce, $shouldDisplayMessages);
71+
$shouldDeleteAllMessages = $input->getOption('all');
6672

67-
return 0;
68-
}
73+
$idsCount = \count($ids);
74+
if (!$shouldDeleteAllMessages && !$idsCount) {
75+
throw new RuntimeException('Please specify at least one message id. If you want to remove all messages, use the "--all" option.');
76+
} elseif ($shouldDeleteAllMessages && $idsCount) {
77+
throw new RuntimeException('You cannot specify message ids when using the "--all" option.');
78+
}
79+
80+
$shouldDisplayMessages = $input->getOption('show-messages') || 1 === $idsCount;
6981

70-
private function removeMessages(string $failureTransportName, array $ids, ReceiverInterface $receiver, SymfonyStyle $io, bool $shouldForce, bool $shouldDisplayMessages): void
71-
{
7282
if (!$receiver instanceof ListableReceiverInterface) {
7383
throw new RuntimeException(sprintf('The "%s" receiver does not support removing specific messages.', $failureTransportName));
7484
}
7585

86+
if ($shouldDeleteAllMessages) {
87+
$this->removeAllMessages($receiver, $io, $shouldForce, $shouldDisplayMessages, $failureTransportName);
88+
} else {
89+
$this->removeMessagesById($ids, $receiver, $io, $shouldForce, $shouldDisplayMessages, $failureTransportName);
90+
}
91+
92+
return 0;
93+
}
94+
95+
private function removeMessagesById(array $ids, ListableReceiverInterface $receiver, SymfonyStyle $io, bool $shouldForce, bool $shouldDisplayMessages, string $failureTransportName): void
96+
{
7697
foreach ($ids as $id) {
7798
$this->phpSerializer?->acceptPhpIncompleteClass();
7899
try {
@@ -99,4 +120,26 @@ private function removeMessages(string $failureTransportName, array $ids, Receiv
99120
}
100121
}
101122
}
123+
124+
private function removeAllMessages(ListableReceiverInterface $receiver, SymfonyStyle $io, bool $shouldForce, bool $shouldDisplayMessages, string $failureTransportName): void
125+
{
126+
$count = 0;
127+
foreach ($receiver->all() as $envelope) {
128+
if ($shouldDisplayMessages) {
129+
$this->displaySingleMessage($envelope, $io);
130+
}
131+
132+
if ($shouldForce) {
133+
$receiver->reject($envelope);
134+
}
135+
136+
++$count;
137+
}
138+
139+
if ($shouldForce) {
140+
$io->note(sprintf('%d messages were removed.', $count));
141+
} else {
142+
$io->note(sprintf('%d messages found in the "%s" transport, use the "--force" option to remove them.', $count, $failureTransportName));
143+
}
144+
}
102145
}

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

+84-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Messenger\Tests\Command;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Console\Exception\RuntimeException;
1516
use Symfony\Component\Console\Tester\CommandCompletionTester;
1617
use Symfony\Component\Console\Tester\CommandTester;
1718
use Symfony\Component\DependencyInjection\ServiceLocator;
@@ -207,7 +208,7 @@ public function testCompleteId()
207208
$globalFailureReceiverName = 'failure_receiver';
208209

209210
$receiver = $this->createMock(ListableReceiverInterface::class);
210-
$receiver->expects($this->once())->method('all')->with(50)->willReturn([
211+
$receiver->expects($this->once())->method('all')->willReturn([
211212
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('2ab50dfa1fbf')]),
212213
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('78c2da843723')]),
213214
]);
@@ -233,7 +234,7 @@ public function testCompleteIdWithSpecifiedTransport()
233234
$anotherFailureReceiverName = 'another_receiver';
234235

235236
$receiver = $this->createMock(ListableReceiverInterface::class);
236-
$receiver->expects($this->once())->method('all')->with(50)->willReturn([
237+
$receiver->expects($this->once())->method('all')->willReturn([
237238
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('2ab50dfa1fbf')]),
238239
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('78c2da843723')]),
239240
]);
@@ -253,4 +254,85 @@ public function testCompleteIdWithSpecifiedTransport()
253254

254255
$this->assertSame(['2ab50dfa1fbf', '78c2da843723'], $suggestions);
255256
}
257+
258+
public function testOptionAllIsSetWithIdsThrows()
259+
{
260+
$globalFailureReceiverName = 'failure_receiver';
261+
262+
$serviceLocator = $this->createMock(ServiceLocator::class);
263+
$serviceLocator->expects($this->once())->method('has')->with($globalFailureReceiverName)->willReturn(true);
264+
$serviceLocator->expects($this->any())->method('get')->with($globalFailureReceiverName)->willReturn($this->createMock(ListableReceiverInterface::class));
265+
266+
$command = new FailedMessagesRemoveCommand('failure_receiver', $serviceLocator);
267+
$tester = new CommandTester($command);
268+
269+
$this->expectException(RuntimeException::class);
270+
$this->expectExceptionMessage('You cannot specify message ids when using the "--all" option.');
271+
$tester->execute(['id' => [20], '--all' => true]);
272+
}
273+
274+
public function testOptionAllIsSetWithoutForceThrows()
275+
{
276+
$globalFailureReceiverName = 'failure_receiver';
277+
278+
$receiver = $this->createMock(ListableReceiverInterface::class);
279+
$receiver->expects($this->once())->method('all')->willReturn([
280+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('2ab50dfa1fbf')]),
281+
Envelope::wrap(new \stdClass(), [new TransportMessageIdStamp('78c2da843723')]),
282+
]);
283+
284+
$serviceLocator = $this->createMock(ServiceLocator::class);
285+
$serviceLocator->expects($this->once())->method('has')->with($globalFailureReceiverName)->willReturn(true);
286+
$serviceLocator->expects($this->any())->method('get')->with($globalFailureReceiverName)->willReturn($receiver);
287+
288+
$command = new FailedMessagesRemoveCommand('failure_receiver', $serviceLocator);
289+
$tester = new CommandTester($command);
290+
291+
$tester->execute(['--all' => true]);
292+
293+
$this->assertSame(0, $tester->getStatusCode());
294+
$this->assertStringContainsString('2 messages found in the "failure_receiver" transport, use the "--force" option to remove them.', $tester->getDisplay());
295+
}
296+
297+
public function testOptionAllIsNotSetNorIdsThrows()
298+
{
299+
$globalFailureReceiverName = 'failure_receiver';
300+
301+
$serviceLocator = $this->createMock(ServiceLocator::class);
302+
$serviceLocator->expects($this->once())->method('has')->with($globalFailureReceiverName)->willReturn(true);
303+
$serviceLocator->expects($this->any())->method('get')->with($globalFailureReceiverName)->willReturn($this->createMock(ListableReceiverInterface::class));
304+
305+
$command = new FailedMessagesRemoveCommand('failure_receiver', $serviceLocator);
306+
$tester = new CommandTester($command);
307+
308+
$this->expectException(RuntimeException::class);
309+
$this->expectExceptionMessage('Please specify at least one message id. If you want to remove all messages, use the "--all" option.');
310+
$tester->execute([]);
311+
}
312+
313+
public function testRemoveAllMessages()
314+
{
315+
$globalFailureReceiverName = 'failure_receiver';
316+
$receiver = $this->createMock(ListableReceiverInterface::class);
317+
318+
$series = [
319+
new Envelope(new \stdClass()),
320+
new Envelope(new \stdClass()),
321+
new Envelope(new \stdClass()),
322+
new Envelope(new \stdClass()),
323+
];
324+
325+
$receiver->expects($this->once())->method('all')->willReturn($series);
326+
327+
$serviceLocator = $this->createMock(ServiceLocator::class);
328+
$serviceLocator->expects($this->once())->method('has')->with($globalFailureReceiverName)->willReturn(true);
329+
$serviceLocator->expects($this->any())->method('get')->with($globalFailureReceiverName)->willReturn($receiver);
330+
331+
$command = new FailedMessagesRemoveCommand($globalFailureReceiverName, $serviceLocator);
332+
$tester = new CommandTester($command);
333+
$tester->execute(['--all' => true, '--force' => true, '--show-messages' => true]);
334+
335+
$this->assertStringContainsString('Failed Message Details', $tester->getDisplay());
336+
$this->assertStringContainsString('4 messages were removed.', $tester->getDisplay());
337+
}
256338
}

0 commit comments

Comments
 (0)
0