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.
Then click on the Activate button:
Copy keys, tokens, and secrets to a safe place and then click the done button:
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:
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:
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:
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:
$ 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.