WPCloud Deploy Documentation

All About WP Crons

Introduction

The WP CRON process is an integral component of WordPress and is required to keep WordPress healthy.  Straight out of the box it sets up 11 jobs (as of WP 6.0) that must each be run on a regular basis.  Some need to run every hour and others can be run once a week.

 

How Does A Cron Process Get Triggered?

By default, every time WordPress receives a request it will first check to see if it’s time to run any jobs.  If it is, it will run them.  As you might expect, on a heavy site, this check incurs a performance penalty.  And, in the event that a job needs to be run, the user will need to wait for that to run before the request can be completed.

Another issue can occur if a site isn’t accessed very often – scheduled jobs might never be run or might run late.

There is a solution to both of these issues though.

You can disable the normal ‘check on every request’ function with a WP-CONFIG.php flag (DISABLE_WP_CRON).  Then, you can schedule the check to be done using a LINUX cron to call the WordPress cron-check directly.  This means you can schedule the check to run once every 15 minutes or once every hour instead of on every request.

As you might expect, with WPCloudDeploy it is easy to make this switch for each site.

Cron Conflicts – A Deeper Dive Into How WP Cron Works

What happens if you set a cron schedule to run every minute and a job fails to complete in that time? Does a new job get started?

The answer to this actually depend on how WP CRON was invoked.

If you execute it with an HTTP request with ‘doing_wp_cron’ in the GET string, it will check if another wp-cron process has set a lock and exit if it has. By default, this is how WordPress executes it when checking on every request.

It is easily done this way using a Linux cron as well. In crontab you can enter something like this:

*/10 * * * * /usr/bin/wget -q -O "http://www.example.com/wp-cron.php?doing_wp_cron=`date +\%s.\%N`" > /dev/null 2>&1

Using PHP CLI

You can also call the WP CRON check process directly from the command line using PHP CLI.

In this case, things get a little bit more funky.

WordPress will check the WP_CRON_LOCK_TIMEOUT constant which defaults to sixty seconds. If the existing process has been running for longer than that, it claims the lock for its own and proceeds to run scheduled jobs starting all over at the beginning.

You should read that bolded part again because it has some ramifications.  Though, most of the time it is not as huge an issue as you might think.

WP-CRON reschedules and un-schedules jobs as it goes. Right before it runs a job, it un-schedules it. This usually prevents the job from running twice. And right after it finishes executing a job, it checks to make sure it still owns the lock. If it does not, it exits.  If it still holds the lock, it will re-schedule the job that was just finished so it can run again at its future scheduled time.

That sounds good, right?

Here’s where an issue can occur:

Lets assume you have some jobs that take twenty minutes to run and others that take 5 minutes to run. You start WP-CRON from the command line and it chugs away at the 20 minute job for a bit. Then another WP-CRON instance starts.

That second instance sees that the lock is older than the sixty second timeout and claims the lock for itself.  It then starts over at the beginning.  So now you have two instances running – one holding the lock and one not holding the lock.

The first process unscheduled and rescheduled jobs as it went, but if the jobs are in the every-5-minutes queue, they are now ripe to be run again.  So the second process starts them over again.

The first process gets to the end of the 20 minute job it was on, sees it no longer owns the lock, and quits. It does not reschedule the jobs that it unscheduled when it started.  This can cause jobs to be lost and never be run again.

Also, because wp-cron unschedules jobs just before running them, if it were to die between doing that and the job completing, due to memory running out or something similar, the job would just be lost.

Race Conditions

There is also a possible race condition. If another process both claims the lock after the first process checks it and before that process unschedules the next job, that job will be run twice. On a bogged down server, the likelihood of hitting that condition might be larger.

 

Share: