For the purpose of speeding up Magento frontend performance, some tasks are executed in separate processes in the background. Stock updating, cache flushing, catalog updating, product price calculating: these are very heavy and time-consuming processes, that’s why as general they are executed in the background and usually by Cron. The description of how to add 3 processes in Cron you can find in Magento 2 Developer Documentation.
* * * * * <path to php binary> <magento install dir>/bin/magento cron:run
* * * * * <path to php binary> <magento install dir>/update/cron.php
* * * * * <path to php binary> <magento install dir>/bin/magento setup:cron:run
The first command is primary, it initializes Cron in Magento 2 configuration. The second and the third are used for Magento 2 and its components updating. It’s enough to add only the first command in Cron for the basic work with it.
By the way, you can specify in the admin panel on what stage index execution should be done.
On the current page you are able to choose indexing mode. There are 2 available modes in Magento 2:
- Update on Save;
- Update by Schedule.
When selecting the first mode: indexing is executed by saving the product, category, etc. But this method has some disadvantages: saving process takes much more time than usually, but all the changes are applied immediately.
When selecting the second mode: everything goes conversely. It doesn’t affect to saving process, and all changes are applied after saving. As a rule the second mode is preferred. So let’s consider indexing process exactly in this mode.
So what happens when we launch the following command:
<path to php binary> <magento install dir>/bin/magento cron:run
After this command is launched we are getting into object class
Magento\Cron\Console\Command\CronCommand into the execute method which is inherited from Symfony\Component\Console\Command\Command, as well as all console commands in Magento 2.
Initialization of input variables is performed in Magento\Cron\Console\Command\CronCommand::execute(), as well as process status check. If the check result is positive, then Magento\Framework\App\Cron object class is created and launch() method is called. Establishing of area code, configuration loading and calling to “default” event are executed in Magento\Framework\App\Cron::launch() method. Any modules and classes can subscribe to this event and all subscribed classes will be executed when the cron:run command is running. Here is the syntax that describes how it is possible to subscribe to this event:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<observer name="catalogrule" instance="Magento\CatalogRule\Observer\ProcessAdminFinalPriceObserver" />
It bears noting, that the event is called in areaCode=’crontab’, that’s why events.xml file should be placed in crontab directory of your module. This event is called anytime when cron:run command is launched, therefore you should not write here long-time execution commands, because it can be cause of blocking commands stack that Cron launches.
And Magento_Cron – Magento\Cron\Observer\ProcessCronQueueObserver modules observer is subscribed to this (“default”) event. The algorithm of Cron-tasks queгe is executed in particular object of the following class in the execute method. And for example this is how the Cron-task should be scheduled (the file must be placed in etc/crontab.xml folder):
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
<job name="backend_clean_cache" instance="Magento\Backend\Cron\CleanCache" method="execute">
<schedule>30 2 * * *</schedule>
This Cron-task will be processed in the object of class Magento\Cron\Observer\ProcessCronQueueObserver::execute().
Additionally all the Cron groups that are specified in order of Cron-tasks creating in your module, are being chosen in the current method. For example, this is id=”default” group. Initially there are 4 groups are created in Magento 2: default, staging, index, catalog_events.
You can find these groups in Stores->Configuration->Advanced->System.
You are able to set up logs storage, the frequency of queue creating for the certain group and other parameters for each group. One of the most important property is “Use Separate Process”. It creates a new separate process for the certain group when you flag the “true” field.
If for some reasons, already existing groups don’t suit you, you can create a new one. For that, you should create a file with cron_groups.xml name in etc/ directory of your module and declare default parameters for this new group:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/cron_groups.xsd">
<schedule_generate_every tooltip="Be careful changes in schedule may affect date picker for scheduled updates">1</schedule_generate_every>
After you chose a group in execute method of Magento\Cron\Observer\ProcessCronQueueObserver class object, a call to shell command is happening, which is the launch of cron:run command with parameters for certain group.
The command is running with the following parameters:
/usr/local/bin/php '/var/www/html/bin/magento' cron:run --group=index --bootstrap=standaloneProcessStarted=1 > /dev/null &
As you can see, this command is running for index group tasks and the flag –bootstrap=standaloneProcessStarted=1 means that any child processes has not been created, otherwise there could happen that each command creates Crons for all the groups and the process would enter an infinite loop.
Basically, there is no problem to launch this command by yourself in the console, and then tasks only from one group will be processed. But you have to be very careful and let the process be finished.
It is important, because in case of incorrect stop, the current tasks would not switch their status from running to success (or error). And then, by the next call to task, we will always get the result that the command is in progress. Basically it will lead to task call failure. There is only one way how to solve this problem: you have to delete “freezed” tasks manually from cron_schedule table.
It should be noticed, that for each group there is a Cron task created. That’s why the groups of tasks are executed individually. At the same time these groups are executed consecutively, and the blocking could happen when the execution of some tasks takes too much time. Therefore, it is much better to create a new group for heavy tasks. Then this group would be called in a separate process, that wouldn’t lead to blocking other tasks.
In summary we have just got acquainted with the Cron job in Magento 2. And you can note that Cron job in Magento 2 is pretty simple, logical and flexible.