Hello everyone!

We have been investing plenty of personal time and energy for many years to share our knowledge with you all. However, we now need your help to keep this blog running. All you have to do is just click one of the adverts on the site, otherwise it will sadly be taken down due to hosting etc. costs. Thank you.

Possible ways of handling RabbitMQ errors when consuming messages with consumers are shown below as follows. Just focus on the try ... catch block for now. Example uses RabbitMqBundle.


Consumer


namespace Application\FrontendBundle\Consumer;

use Application\FrontendBundle\Entity\OrderLog;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use OldSound\RabbitMqBundle\RabbitMq\ConsumerInterface;
use PhpAmqpLib\Exception\AMQPBasicCancelException;
use PhpAmqpLib\Message\AMQPMessage;
use Symfony\Component\HttpKernel\Log\LoggerInterface;

class OrderCreateConsumer implements ConsumerInterface
{
private $entityManager;
private $logger;

public function __construct(
EntityManagerInterface $entityManager,
LoggerInterface $logger
) {
$this->entityManager = $entityManager;
$this->logger = $logger;
}

public function execute(AMQPMessage $message)
{
$body = json_decode($message->body, true);

try {
$this->log($body);

echo sprintf('Order create - ID:%s @ %s ...', $body['order_id'], date('Y-m-d H:i:s')).PHP_EOL;
} catch (Exception $e) {
// Option 1:
// $this->logger->error(json_encode($message));

// Option 2:
// throw new AMQPBasicCancelException(json_encode($message));

// Option 3:
// return false;

// Option 4:
// return ConsumerInterface::MSG_REJECT_REQUEUE;

// Option 5:
// return ConsumerInterface::MSG_REJECT;
}
}

private function log($message)
{
$log = new OrderLog();
$log->setAction(OrderLog::CREATE);
$log->setMessage($message);

$this->entityManager->persist($log);
$this->entityManager->flush();
}
}

Options explained


Assume that you have two consumers are running in terminal with $ app/console rabbitmq:consumer -m 100 order_create command.



Result


I would suggest you to go for Option 1 for obvious reasons. The Option 5 is the same as Option 1 but it just doesn't take a log.


Note: If it was a real world case, I would suggest you to use RabbitMQ's Dead Letter Exchange feature then use Option 1 and Option 5 together in your application. In that case, Option 1 would take a log and the Option 5 would direct the message to Dead Letter Exchange where you would investigate the message and do something about it. I have a full example in this blog.