/**
  * @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_message_when_exception_occurred()
 {
     $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 \Exception())->shouldBeCalled();
     $amqpCommandConsumerCallback = new AmqpCommandConsumerCallback($commandBus->reveal(), $messageFactory->reveal());
     $deliveryResult = $amqpCommandConsumerCallback($envelope->reveal(), $queue->reveal());
     $this->assertEquals(DeliveryResult::MSG_REJECT(), $deliveryResult);
 }
 /**
  * @param Envelope $envelope
  * @return DeliveryResult
  */
 protected function handleInternalMessage(Envelope $envelope) : DeliveryResult
 {
     if ('shutdown' === $envelope->getType()) {
         $this->logger->info('Shutdown message received');
         $this->shutdown();
         $result = DeliveryResult::MSG_ACK();
     } elseif ('reconfigure' === $envelope->getType()) {
         $this->logger->info('Reconfigure message received');
         try {
             list($idleTimeout, $target, $prefetchSize, $prefetchCount) = json_decode($envelope->getBody());
             if (is_numeric($idleTimeout)) {
                 $idleTimeout = (double) $idleTimeout;
             }
             Assertion::float($idleTimeout);
             Assertion::min($target, 0);
             Assertion::min($prefetchSize, 0);
             Assertion::min($prefetchCount, 0);
         } catch (\Throwable $e) {
             $this->logger->error('Exception during reconfiguration: ' . $e->getMessage());
             return DeliveryResult::MSG_REJECT();
         }
         $this->idleTimeout = $idleTimeout;
         $this->target = $target;
         $this->queue->getChannel()->qos($prefetchSize, $prefetchCount);
         $this->blockSize = $prefetchCount;
         $result = DeliveryResult::MSG_ACK();
     } elseif ('ping' === $envelope->getType()) {
         $this->logger->info('Ping message received');
         $result = DeliveryResult::MSG_ACK();
     } else {
         $this->logger->error('Invalid internal message: ' . $envelope->getType());
         $result = DeliveryResult::MSG_REJECT();
     }
     return $result;
 }