/** * @param Envelope $envelope * @param Queue $queue * @return DeliveryResult */ public function __invoke(Envelope $envelope, Queue $queue) : DeliveryResult { $data = json_decode($envelope->getBody(), true); if (!isset($data['created_at'])) { return DeliveryResult::MSG_REJECT(); } $data['created_at'] = DateTimeImmutable::createFromFormat('Y-m-d\\TH:i:s.u', $data['created_at'], new DateTimeZone('UTC')); if (false === $data['created_at']) { return DeliveryResult::MSG_REJECT(); } try { $command = $this->messageFactory->createMessageFromArray($envelope->getType(), $data); $this->commandBus->dispatch($command); } catch (\Throwable $e) { while ($e = $e->getPrevious()) { if ($e instanceof ConcurrencyException) { return DeliveryResult::MSG_REJECT_REQUEUE(); } } return DeliveryResult::MSG_REJECT(); } return DeliveryResult::MSG_ACK(); }
/** * @test */ public function it_rejects_and_requeues_message_when_concurrency_exception_occured() { $time = (string) microtime(true); if (false === strpos($time, '.')) { $time .= '.0000'; } $now = \DateTimeImmutable::createFromFormat('U.u', $time); $envelope = $this->prophesize(Envelope::class); $envelope->getBody()->willReturn('{"message_name":"test-command","uuid":"ccefedef-85e1-4fd0-b247-ed13d378b050","version":1,"payload":[],"metadata":[],"created_at":"' . $now->format('Y-m-d\\TH:i:s.u') . '"}')->shouldBeCalled(); $envelope->getType()->willReturn('test-command')->shouldBeCalled(); $queue = $this->prophesize(Queue::class); $command = $this->prophesize(Command::class); $messageFactory = $this->prophesize(MessageFactory::class); $messageFactory->createMessageFromArray('test-command', ['message_name' => 'test-command', 'uuid' => 'ccefedef-85e1-4fd0-b247-ed13d378b050', 'version' => 1, 'payload' => [], 'metadata' => [], 'created_at' => $now])->willReturn($command->reveal())->shouldBeCalled(); $commandBus = $this->prophesize(CommandBus::class); $commandBus->dispatch($command)->willThrow(new MessageDispatchException('', 0, new ConcurrencyException()))->shouldBeCalled(); $amqpCommandConsumerCallback = new AmqpCommandConsumerCallback($commandBus->reveal(), $messageFactory->reveal()); $deliveryResult = $amqpCommandConsumerCallback($envelope->reveal(), $queue->reveal()); $this->assertEquals(DeliveryResult::MSG_REJECT_REQUEUE(), $deliveryResult); }
/** * Handle process flag * * @param Envelope $envelope * @param $flag * @return void */ protected function handleProcessFlag(Envelope $envelope, DeliveryResult $flag) { $this->countMessagesConsumed++; switch ($flag) { case DeliveryResult::MSG_REJECT(): $this->queue->nack($envelope->getDeliveryTag(), Constants::AMQP_NOPARAM); $this->logger->debug('Rejected message', $this->extractMessageInformation($envelope)); break; case DeliveryResult::MSG_REJECT_REQUEUE(): $this->queue->nack($envelope->getDeliveryTag(), Constants::AMQP_REQUEUE); $this->logger->debug('Rejected and requeued message', $this->extractMessageInformation($envelope)); break; case DeliveryResult::MSG_ACK(): $this->countMessagesUnacked++; $this->lastDeliveryTag = $envelope->getDeliveryTag(); $this->timestampLastMessage = microtime(true); $this->ack(); break; case DeliveryResult::MSG_DEFER(): $this->countMessagesUnacked++; $this->lastDeliveryTag = $envelope->getDeliveryTag(); $this->timestampLastMessage = microtime(true); break; } }