/** * Start consumer * * @param int $msgAmount * @throws Exception\QueueException */ public function consume(int $msgAmount = 0) { Assertion::min($msgAmount, 0); $this->target = $msgAmount; $this->blockSize = $this->queue->getChannel()->getPrefetchCount(); if (!$this->timestampLastAck) { $this->timestampLastAck = microtime(true); } $callback = function (Envelope $envelope) { try { $processFlag = $this->handleDelivery($envelope, $this->queue); } catch (\Throwable $e) { $this->logger->error('Exception during handleDelivery: ' . $e->getMessage()); $this->handleException($e); $processFlag = DeliveryResult::MSG_REJECT_REQUEUE(); } $this->handleProcessFlag($envelope, $processFlag); $now = microtime(true); if ($this->countMessagesUnacked > 0 && ($this->countMessagesUnacked === $this->blockSize || $now - $this->timestampLastAck > $this->idleTimeout)) { $this->ackOrNackBlock(); } if ($this->usePcntlSignalDispatch) { // Check for signals pcntl_signal_dispatch(); } if (!$this->keepAlive || 0 !== $this->target && $this->countMessagesConsumed >= $this->target) { $this->ackOrNackBlock(); $this->queue->cancel($this->consumerTag); $this->shutdown(); return false; } }; try { $this->queue->consume($callback, Constants::AMQP_NOPARAM, $this->consumerTag); } catch (Exception\QueueException $e) { $this->logger->error('Exception: ' . $e->getMessage()); $this->ackOrNackBlock(); // hack for different drivers $channel = $this->queue->getChannel(); if ($channel instanceof Driver\PhpAmqpLib\Channel) { $channel->getResource()->close(); // preferred, but not present in amqp-extension } elseif ($channel instanceof Driver\AmqpExtension\Channel) { $channel->getConnection()->reconnect(); // needed in order to destroy (and close) the channel } } }