Introduction
Hello!
In today's article, I'll cover a topic that's not too tricky, but can be a bit annoying without some useful tips. Specifically, we'll dive into Magento 2 ( Mage-OS / Adobe Commerce ) to discuss cron jobs, their configurations, and the process of rescheduling them and altering their execution group.
You might wonder, why bother changing the schedule or group of a cron job? Let's find out.
Why Adjust the Cron Schedule?
Occasionally, a cron job might execute too frequently, leading to server load issues or even deadlocks. On the other hand, if it doesn't run often enough, you could be left waiting for emails that take an hour to send. This scenario becomes particularly tricky when these cron jobs are associated with third-party extensions.
Let's imagine we are using 3rd party Feed and Mailing extensions, and we are not OK with their cron jobs schedule.
How can you modify the execution patterns of these cron jobs without tampering with the third-party code directly? By implementing changes in your own codebase β your module. Let's explore this next.
Rescheduling Cron Jobs
Let's have a look at the cron job of the Feed extension feed_generation
.
Here is its definition:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
<group id="default">
...
<job name="feed_generation" instance="\Feed\Cron\FeedGenerator" method="execute">
<schedule>* * * * *</schedule>
</job>
...
</group>
</config>
Executing every minute, this job can impose a significant server load. We certainly don't need a new feed every 60 seconds!
To modify its frequency, we'll craft a module, Devto_ChangeFeedSchedule
, and incorporate an etc/config.xml
file within.
So, the structure would look like this:
Devto_ChangeFeedSchedule/
β
βββ etc/
β βββ config.xml # our config file
β βββ module.xml
β
βββ registration.php
β
βββ composer.json
The etc/config.xml
should contain:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<crontab>
<default> <!-- cron group -->
<jobs>
<feed_generation> <!-- job name -->
<schedule>
<cron_expr>0 * * * *</cron_expr> <!-- new cron execution schedule -->
</schedule>
</feed_generation>
</jobs>
</default>
</crontab>
</default>
</config>
And last but not least - add sequence into etc/module.xml
to declare dependency over Feed module and configs apply order:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Devto_ChangeFeedSchedule" >
<sequence>
<!-- makes Devto_ChangeFeedSchedule configs be applied after Feed extension configs -->
<module name="Vendor_FeedExtesnion"/>
</sequence>
</module>
</config>
Once the module Devto_ChangeFeedSchedule
is activated and the cache cleared, your new job schedule will take effect - run every hour but not a minute.
But what about cron groups? Let's delve into that next.
The Need to Change Cron Group
Imagine we're still working with the Feed and Mailing third-party extensions. These extensions utilize distinct cron groups, each operating as an isolated process. Thanks to this, cron groups can run concurrently/parallely, using individual processes.
Now, suppose these two cron jobs conflict, resulting in data inconsistencies in the Feed and Emails. Worse yet, deadlocks
can crop up. You might ask, "Why the deadlocks?"
Well, imagine these extensions read & write the same table, say sales_order_item
. When they run simultaneously, the stage is set for potential deadlocks. π€·ββοΈ
If only these jobs were executed sequentially! By relocating them to a shared group, you can ensure they no longer run in parallel.
Altering the Cron Job's Group
A straightforward (though not perfect) solution would be to transfer the Mailing extension's cron job to the default
group, where the Feed extension's job resides. Here's the Mailing cron job definition:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
<group id="mailing_extension"> <!-- mailing cron group -->
...
<job name="send_mails_from_mailing_extension" instance="\Mailing\Cron\SendMailsCron" method="execute">
<schedule>*/20 * * * *</schedule>
</job>
...
</group>
</config>
However, a small, non-intuitive trick is essential here: Simply changing the group by redefining crontab.xml
won't work. Instead, you need to craft a new cron job while deactivating the old one. This step is necessary since crontab.xml
configurations (especially groups) can't be overridden, only augmented.
For instance, merely defining the send_mails_from_mailing_extension
cron job in the default
group would make it run in both the default
and mailing_extension
groups.
To disable send_mails_from_mailing_extension
, an easy trick is to schedule it for February 30thβa date that doesn't exist!
nerd fact π€: actually February 30 happened in Sweden in 1712
Following our earlier approach, we'd add the following content to the etc/config.xml
in our module, Devto_ChangeMailingJobGroup
:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<crontab>
<default>
<jobs>
<!-- Disable cron execution by scheduling it to Feb 30th. -->
<send_mails_from_mailing_extension>
<schedule>
<cron_expr>0 0 30 2 *</cron_expr>
</schedule>
</send_mails_from_mailing_extension>
</jobs>
</default>
</crontab>
</default>
</config>
Next, define a NEW cron job in the default
group:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
<group id="default"> <!-- default cron group -->
...
<!-- added devto prefix to cron name -->
<job name="devto_send_mails_from_mailing_extension" instance="\Mailing\Cron\SendMailsCron" method="execute">
<schedule>*/20 * * * *</schedule>
</job>
...
</group>
</config>
And do not forget to add Mailing module sequence into etc/module.xml
:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Devto_ChangeMailingJobGroup" >
<sequence>
<!-- makes Devto_ChangeMailingJobGroup configs be applied after Mailing extension configs -->
<module name="Vendor_MailingExtesnion"/>
</sequence>
</module>
</config>
After all changes, the module structure should look like this:
Devto_ChangeMailingJobGroup/
β
βββ etc/
β βββ config.xml # our config file
| βββ crontab.xml # our crontab definition file
β βββ module.xml
β
βββ registration.php
β
βββ composer.json
Once Devto_ChangeMailingJobGroup
is active and the cache refreshed, the send_mails_from_mailing_extension
job will be disabled. Meanwhile, its counterpart, devto_send_mails_from_mailing_extension
, will operate in the default
cron group alongside the Feed cron job.
A Word of Caution on the Default Group
It's vital to recognize that Magento's native cron jobs already densely populate the default
cron group. Overloading it might cause "traffic jams" if:
- Jobs have lengthy runtimes: If your tasks take too long to finish, they could end up waiting in line, slowing things down.
- Overfrequent Scheduling: Setting jobs to run too often can result in backlogs and potential overlaps.
- Overpopulation: Filling the group with too many tasks, even if they are quick, might overwhelm the system.
So, while the default group is convenient, treat it like a city's main highway during rush hour. It can handle a lot, but there's a limit before things get clogged. If you have too many heavy tasks or they're scheduled too frequently, you'll likely end up with delays.
In short, be mindful of the workload you're placing on the default
group and consider creating your own cron groups to avoid conflict of processes.
Conclusion
And that's the lowdown on Magento's cron jobs, how to shuffle their schedules, and adjust their groups without diving into third-party code directly. With the knowledge you've gathered here, tweaking those pesky cron jobs should be much easier π
Thank you for reading!
Top comments (3)
Nice that the article has focused on practical solutions and cautionary advice on overloading the default group. Usually, nobody cares and puts more and more jobs to the default, that's true.
A must-read for Magento developers looking to optimize cron job configurations.
UPD:
module.xml
over modules configs we are aiming to change. Thx @dlmbr for noticing!I haven't been working on Magento 2 for long, but I'm comfortable with my choice and also with the fact that I contacted Amasty for services. By the way, these specialists also provide a wide selection of various extensions, for example, magento 2 shipping table rates, which allow you to create the best website for your clients, completely covering their needs.