Magento – Queue order details in rabbitmq when order is placed in Magento2EE

magento-2.1.7magento2magento2-enterpriserabbit-mq

In Magento2 EE,I need to queue to order details instantly when the order is placed. Rabbitmq is our message broker. I have installed rabbitmq and configured to the Magento2EE by following this link https://inviqa.com/blog/magento-2-tutorial-message-queues. . Everything is working fine. I can push the order array to the queue by giving static order ID.

 <?php

namespace Inviqa\MessageQueueExample\Console;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Magento\Framework\MessageQueue\PublisherInterface;
use Inviqa\MessageQueueExample\Api\MessageInterface;
use Magento\Sales\Model\Order;

class MessagePublishCommand extends Command
{
    const COMMAND_QUEUE_MESSAGE_PUBLISH = 'queue:message:publish';
    const MESSAGE_ARGUMENT = 'message';
    const TOPIC_ARGUMENT = 'topic';

    /**
     * @var PublisherInterface
     */
    protected $publisher;
    protected $order;


    /**
     * @var string
     */
    protected $message;

    /**
     * {@inheritdoc}
     */
    public function __construct(
        PublisherInterface $publisher,
        MessageInterface $message,
        Order $order,
        $name = null
    ) {
        $this->publisher = $publisher;
        $this->message = $message;
        $this->order = $order;
        parent::__construct($name);
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $message = $input->getArgument(self::MESSAGE_ARGUMENT);
        $topic = $input->getArgument(self::TOPIC_ARGUMENT);

        try {

            $_orderId = 000000004; 
            $_order = $this->order->load($_orderId);
            $_items = $_order->getAllVisibleItems();
            foreach ($_items as $_item) {
                $_orderItems[] = [
                    'sku' => $_item->getSku(), 
                    'item_id' => $_item->getId(),
                    'price' => $_item->getPrice(),
                ];

            }
            $message = $_orderItems;

            $this->message->setMessage($message);
            $this->publisher->publish($topic, $this->message);
            /*print_r($message);
            die;*/
           // $output->writeln(sprintf('Published message "%s" to topic "%s"', $message, $topic));
            $output->writeln(sprintf('Published order'));

        } catch (\Exception $e) {
            $output->writeln($e->getMessage());
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName(self::COMMAND_QUEUE_MESSAGE_PUBLISH);
        $this->setDescription('Publish a message to a topic');
        $this->setDefinition([
            new InputArgument(
                self::MESSAGE_ARGUMENT,
                InputArgument::REQUIRED,
                'Message'
            ),
            new InputArgument(
                self::TOPIC_ARGUMENT,
                InputArgument::REQUIRED,
                'Topic'
            ),
        ]);
        parent::configure();
    }
}

Once the order is placed, for pushing order object i have planned to use sales_order_place_after event. But i'm not sure how to pull the result from observer, to this execute action.

Best Answer

Here is the way that I have fulfilled the requirement to send the order details automatically to Queue once the order is placed.

<?php

namespace Test\Module\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\MessageQueue\PublisherInterface;
use Test\Module\Api\MessageInterface;

class Pushqueue implements ObserverInterface
{
    public $orderFacory;
    public $publisher;
    public $message;

    public function __construct(
        \Magento\Sales\Model\Order $orderFacory,
        PublisherInterface $publisher,
        MessageInterface $message,
        $name = null

    ) {
        $this->orderFacory = $orderFacory; 
        $this->publisher = $publisher;
        $this->message = $message;       
        //parent::__construct($name);
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $topic = 'sender';
        $orderIds = $observer->getEvent()->getOrderIds();
         $lastorderId = $orderIds[0];
        try {
            $order = $this->orderFacory->load($lastorderId);

            foreach($order->getAllVisibleItems() as $item){
                $itemsData = array();
                $orderData[]= $item->getData();
                /*$orderData[$itemsData['price']]= $item->getPrice();
                $orderData[$itemsData['quoteItem_id']]= $item->getQuoteItemId();
                $orderData[$itemsData['item_id']]= $item->getItemId();*/
            }
            $orderData[] = $order->getData();


            $this->message->setMessage($orderData);
            $this->publisher->publish($topic, $this->message);

        return $this;

        } catch (Exception $e) {
            print_r($e->getMessage());
        }

    }


}

This observer is getting called with event

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="checkout_onepage_controller_success_action">
    <observer name="test_module" instance="Test\Module\Observer\Pushqueue"  />
</event>
</config>

my communication.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework-message-queue:etc/queue.xsd">
<topic name="sender" request="Test\Module\Api\MessageInterface" />
<topic name="sender2" request="Test\Module\Api\MessageInterface" />
</config>

These are the main files and this link will help you further https://inviqa.com/blog/magento-2-tutorial-message-queues. Please let me know if you need any more details. I would love to help to the one who helps all.. :)