Cron

Cron job XML

Magento uses XML files called crontab.xml to configure what and when cronjobs will be run.

The structure if the file is as so

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <!-- The group that the jobs will run under, normally this will be default, or a custom on -->
    <group id="index"> 
        <!-- The job, the name must be unique for the job to run, the class can be a POPO -->
        <job name="indexer_reindex_all_invalid" instance="Magento\Indexer\Cron\ReindexAllInvalid" method="execute">
            <!-- How often the job should be run. See https://crontab.guru/ for help with this -->
            <schedule>* * * * *</schedule>
        </job>
        <job name="indexer_update_all_views" instance="Magento\Indexer\Cron\UpdateMview" method="execute">
            <schedule>* * * * *</schedule>
        </job>
        <job name="indexer_clean_all_changelogs" instance="Magento\Indexer\Cron\ClearChangelog" method="execute">
            <schedule>0 * * * *</schedule>
        </job>
    </group>
</config>

Updating Cron Jobs

There are several ways that the jobs can be updated, however the most flexible way is to create your own crontab.xml file in a module.

As Magento collects and merges all XML files, you can override any of the values in the file as long as your module is loaded after the module that defines the initial cron job. See here for more instructions on how to enforce this

Using the XML file above as an example, we may want to update the schedule so the indexer_reindex_all_invalid only runs once an hour rather than ever minute. We can achieve this be putting the following into the crontab.xml file in out module

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <group id="index"> 
        <!-- All of the attributes are required, so if you want to keep the functionality copy the entire node from the original XML file -->
        <job name="indexer_reindex_all_invalid" instance="Magento\Indexer\Cron\ReindexAllInvalid" method="execute">
            <!-- We need to update this line -->
            <schedule>1 * * * *</schedule>
        </job>
    </group>
</config>

After clearing the caches and running DI Compile the schedule will be updated. You can use Magerun 2 to confirm this by running the cron list command

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
ec@staging-desktop php n98-magerun2.phar sys:cron:list


  Cronjob List  


+-----------------------------------------------------+----------------+------+------+---+---+----+
| Job                                                 | Group          | m    | h    | D | M | WD |
+-----------------------------------------------------+----------------+------+------+---+---+----+
| ... other crons ...                                 |                | *    | *    | * | * | *  |
| indexer_reindex_all_invalid                         | index          | 1    | *    | * | * | *  |
| ... other crons ...                                 |                | *    | *    | * | * | *  |
+-----------------------------------------------------+----------------+------+------+---+---+----+

Disabling A Cron Job

Magento does not provide a simple way for an individual cron job to be disabled, however we can do this in a round about way using the same concept that we used to update the time.

Rather than updating the schedule, we can replace the class that is called by cron with our own that will do nothing. For example, if we wanted to prevent the indexes getting run automatically by cron, perhaps because we wanted to run that at specific times, we would use the following XML file.

1
2
3
4
5
6
7
8
9
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <group id="index"> 
        <!-- All of the attributes are required, so if you want to keep the functionality copy the entire node from the original XML file -->
        <job name="indexer_reindex_all_invalid" instance="EdmondsCommerce\Indexer\Cron\NullIndexer" method="execute">
            <!-- We need to update this line -->
            <schedule>1 * * * *</schedule>
        </job>
    </group>
</config>

And create the following PHP File.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php

declare(strict_types=1);

namespace EdmondsCommerce\Indexer\Cron;

class NullIndexer
{
    /**
     * The method that is called and does nothing
     */
    public function execute(): void
    {
        //Intentionally do nothing
    }
}

Then when the XML is next compiled the cron job will use our class rather than the Magento one whenever it is called.