|
22 | 22 | use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
23 | 23 | use Symfony\Component\Messenger\Envelope;
|
24 | 24 | use Symfony\Component\Messenger\Event\WorkerMessageReceivedEvent;
|
| 25 | +use Symfony\Component\Messenger\Exception\LogicException; |
25 | 26 | use Symfony\Component\Messenger\MessageBusInterface;
|
26 | 27 | use Symfony\Component\Messenger\Retry\RetryStrategyInterface;
|
27 | 28 | use Symfony\Component\Messenger\Transport\Receiver\ListableReceiverInterface;
|
@@ -109,28 +110,48 @@ protected function execute(InputInterface $input, OutputInterface $output)
|
109 | 110 | throw new RuntimeException('Message id must be passed when in non-interactive mode.');
|
110 | 111 | }
|
111 | 112 |
|
112 |
| - return $this->runInteractive($io, $shouldForce); |
113 |
| - } |
| 113 | + $this->runInteractive($io, $shouldForce); |
114 | 114 |
|
115 |
| - if (!$receiver instanceof ListableReceiverInterface) { |
116 |
| - throw new RuntimeException(sprintf('The "%s" receiver does not support retrying messages by id.', $this->getReceiverName())); |
| 115 | + return; |
117 | 116 | }
|
118 | 117 |
|
119 |
| - foreach ($ids as $id) { |
120 |
| - $envelope = $receiver->find($id); |
121 |
| - if (null === $envelope) { |
122 |
| - throw new RuntimeException(sprintf('The message "%s" was not found.', $id)); |
123 |
| - } |
124 |
| - |
125 |
| - $singleReceiver = new SingleMessageReceiver($receiver, $envelope); |
126 |
| - $this->runWorker($singleReceiver, $io, $shouldForce); |
127 |
| - } |
| 118 | + $this->retrySpecificIds($ids, $io, $shouldForce); |
128 | 119 | $io->success('All done!');
|
129 | 120 | }
|
130 | 121 |
|
131 | 122 | private function runInteractive(SymfonyStyle $io, bool $shouldForce)
|
132 | 123 | {
|
133 |
| - $count = $this->runWorker($this->getReceiver(), $io, $shouldForce); |
| 124 | + $receiver = $this->getReceiver(); |
| 125 | + $count = 0; |
| 126 | + if ($receiver instanceof ListableReceiverInterface) { |
| 127 | + // for listable receivers, find the messages one-by-one |
| 128 | + // this avoids using get(), which for some less-robust |
| 129 | + // transports (like Doctrine), will cause the message |
| 130 | + // to be temporarily "acked", even if the user aborts |
| 131 | + // handling the message |
| 132 | + while (true) { |
| 133 | + $ids = []; |
| 134 | + foreach ($receiver->all(1) as $envelope) { |
| 135 | + $count++; |
| 136 | + |
| 137 | + $id = $this->getMessageId($envelope); |
| 138 | + if (null === $id) { |
| 139 | + throw new LogicException(sprintf('The "%s" receiver is able to list messages by id but the envelope is missing the TransportMessageIdStamp stamp.', $this->getReceiverName())); |
| 140 | + } |
| 141 | + $ids[] = $id; |
| 142 | + } |
| 143 | + |
| 144 | + // break the loop if all messages are consumed |
| 145 | + if (0 === \count($ids)) { |
| 146 | + break; |
| 147 | + } |
| 148 | + |
| 149 | + $this->retrySpecificIds($ids, $io, $shouldForce); |
| 150 | + } |
| 151 | + } else { |
| 152 | + // get() and ask messages one-by-one |
| 153 | + $count = $this->runWorker($this->getReceiver(), $io, $shouldForce); |
| 154 | + } |
134 | 155 |
|
135 | 156 | // avoid success message if nothing was processed
|
136 | 157 | if (1 < $count) {
|
@@ -178,4 +199,23 @@ private function runWorker(ReceiverInterface $receiver, SymfonyStyle $io, bool $
|
178 | 199 |
|
179 | 200 | return $count;
|
180 | 201 | }
|
| 202 | + |
| 203 | + private function retrySpecificIds(array $ids, SymfonyStyle $io, bool $shouldForce) |
| 204 | + { |
| 205 | + $receiver = $this->getReceiver(); |
| 206 | + |
| 207 | + if (!$receiver instanceof ListableReceiverInterface) { |
| 208 | + throw new RuntimeException(sprintf('The "%s" receiver does not support retrying messages by id.', $this->getReceiverName())); |
| 209 | + } |
| 210 | + |
| 211 | + foreach ($ids as $id) { |
| 212 | + $envelope = $receiver->find($id); |
| 213 | + if (null === $envelope) { |
| 214 | + throw new RuntimeException(sprintf('The message "%s" was not found.', $id)); |
| 215 | + } |
| 216 | + |
| 217 | + $singleReceiver = new SingleMessageReceiver($receiver, $envelope); |
| 218 | + $this->runWorker($singleReceiver, $io, $shouldForce); |
| 219 | + } |
| 220 | + } |
181 | 221 | }
|
0 commit comments