Convert REST API Web endpoints from Synchronous to Asynchronous in Magento 2

Hello my friends,

Today I am going to teach you how to convert any Magento 2 REST Web endpoint from Synchronous to Asynchronous method in Magento 2.

An asynchronous web endpoint intercepts messages to a Web API and writes them to the message queue. Each time the system accepts such an API request, it generates a UUID identifier. Magento includes this UUID when it adds the message to the queue. Then, a consumer reads the messages from the queue and executes them one by one.

This method requires you to have async.operations.all constantly running so keep that in mind to edit env.php file and remove async.operations.all from consumer_runners basically removing this one that handles asynchronous and bulk API messages to be executed as a Magento 2 Cron task.

php bin/magento queue:consumers:start async.operations.all  

Note: You can configure supervisors or systemyd service to run this as a Service with the config to restart on the first minute after midnight to avoid known issues with certain Memory leaks which we are not going to talk about much today.

The route to all asynchronous calls contains the prefix /async, added before /V1 of a standard synchronous endpoint.

As a Demo, I have installed the latest Magento 2.4.3 version. You can use well known Gitpod.io service and my example for the Dev environment on the https://github.com/nemke82/magento2gitpod following link.

First of all, make sure that your app/etc/env.php file is configured with correct RabbitMQ credentials since we are going to utilize REST endpoint asynchronous way using rabbitmq broker.

Navigate to the Dashboard, and under System --> Integrations and add a new integration.

alt

Then click on the Activate button:
alt

Copy keys, tokens, and secrets to a safe place and then click the done button:
alt

Next, you can log in to the RabbitMQ GUI to check if messages are being sent and if async.operations.all queue exists. This is how it looks like when everything is operational and ready:
alt

Now is a good time to test POST requests. In my example, I have used the famous/known tool Postman and the task is to create a demo Customer. This article https://devdocs.magento.com/guides/v2.4/rest/tutorials/orders/order-create-customer.html guided me an example with the correct Payload to send a request to my Demo Magento 2 installation.

So URL with POST selected is:
https://URL-TO-MAGENTO/rest/all/V1/customers

OAuth 1.0 and entered credentials:
alt

With following body payload:

{
  "customer": {
    "email": "async-jdoe1@example.com",
    "firstname": "Jane-async1",
    "lastname": "Doe-async1",
    "addresses": [
      {
        "defaultShipping": true,
        "defaultBilling": true,
        "firstname": "Jane",
        "lastname": "Doe",
        "region": {
          "regionCode": "NY",
          "region": "New York",
          "regionId": 43
        },
        "postcode": "10755",
        "street": [
          "123 Oak Ave"
        ],
        "city": "Purchase",
        "telephone": "512-555-1111",
        "countryId": "US"
      }
    ]
  },
  "password": "Password1"
}

Now the first test is using Synchronous way, executed and it went well:
alt

But still, nothing is going Async way, we just sent a REST API call to Magento and it is done. Now let's try to change the POST URL

From:
https://URL-OF-MAGENTO/rest/all/V1/customers

To:
https://URL-OF-MAGENTO/rest/all/async/V1/customers

And execute:
alt

alt

$ n98-magerun2 customer:list
+----+--------------+------------+-------------------------+---------+---------------------+
| id | firstname    | lastname   | email                   | website | created_at          |
+----+--------------+------------+-------------------------+---------+---------------------+
| 1  | Jane-async1  | Doe-async1 | async-jdoe1@example.com | 1       | 2021-10-07 20:10:10 |
| 2  | Jane-async12 | Doe-async2 | async-jdoe2@example.com | 1       | 2021-10-07 20:13:07 |
+----+--------------+------------+-------------------------+---------+---------------------+

Exactly how the https://devdocs.magento.com/guides/v2.4/rest/asynchronous-web-endpoints.html article advertises. It changed behavior from Synchronous to Asynchronous and went directly to RabbitMQ and got consumed. I've tested the time of execution between them and the Asynchronous way is a lot faster and it does not lock Database with MySQL queries at all. My idea is to push a variable and try to create 1000 customers using the Async way and compare it with the Synchronous way. The next step is to create a module that is going to convert the REST API endpoint or simply create a Composer patch by patching a Magento 2 Core module. Just make sure that the RabbitMQ broker is always ready and constantly running.