/**
  * @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);
 }
Пример #3
0
 /**
  * @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;
 }
Пример #4
0
 /**
  * @param Envelope $envelope
  * @param Queue $queue
  * @return DeliveryResult
  */
 protected function handleDelivery(Envelope $envelope, Queue $queue) : DeliveryResult
 {
     $this->countMessagesConsumed++;
     $this->countMessagesUnacked++;
     $this->lastDeliveryTag = $envelope->getDeliveryTag();
     $this->timestampLastMessage = microtime(true);
     $this->ack();
     $this->logger->debug('Handling delivery of message', $this->extractMessageInformation($envelope));
     if ($envelope->getAppId() === 'Humus\\Amqp') {
         $this->handleInternalMessage($envelope);
         return DeliveryResult::MSG_ACK();
     }
     try {
         $request = $this->requestFromEnvelope($envelope);
         $callback = $this->deliveryCallback;
         $response = $callback($request);
         if ('' === $request->id()) {
             // notifications have no reply
             return DeliveryResult::MSG_ACK();
         }
         if (!$response instanceof JsonRpcResponse) {
             $response = JsonRpcResponse::withResult($envelope->getCorrelationId(), $response);
         }
     } catch (Exception\InvalidJsonRpcVersion $e) {
         $this->logger->error('Invalid json rpc version', $this->extractMessageInformation($envelope));
         $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32600));
     } catch (Exception\InvalidJsonRpcRequest $e) {
         $this->logger->error('Invalid json rpc request', $this->extractMessageInformation($envelope));
         $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32600));
     } catch (Exception\JsonParseError $e) {
         $this->logger->error('Json parse error', $this->extractMessageInformation($envelope));
         $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32700));
     } catch (\Throwable $e) {
         $extra = $this->extractMessageInformation($envelope);
         $extra['exception_class'] = get_class($e);
         $extra['exception_message'] = $e->getMessage();
         $extra['exception_trace'] = $e->getTraceAsString();
         $this->logger->error('Exception occurred', $extra);
         $response = JsonRpcResponse::withError($envelope->getCorrelationId(), new JsonRpcError(JsonRpcError::ERROR_CODE_32603));
     }
     $this->sendReply($response, $envelope);
     return DeliveryResult::MSG_ACK();
 }