[wp-trac] [WordPress Trac] #42866: WordPress Community Scheduler Interval Bug
WordPress Trac
noreply at wordpress.org
Mon Dec 11 07:26:14 UTC 2017
#42866: WordPress Community Scheduler Interval Bug
--------------------------+-----------------------------
Reporter: mrperl | Owner:
Type: defect (bug) | Status: closed
Priority: normal | Milestone:
Component: Cron API | Version: 4.4.2
Severity: normal | Resolution: worksforme
Keywords: | Focuses: administration
--------------------------+-----------------------------
Changes (by dd32):
* status: new => closed
* resolution: => worksforme
* milestone: Awaiting Review =>
Comment:
Hi @mrperl and welcome to Trac.
It appears that cron is working as expected here to me - although I can
see why you'd see differently.
The WordPress cron is a best-effort scheduler, and not a guaranteed
scheduler, it runs based on non-cached visits to WordPress in most
situations.
Here's an example of what I think is happening here:
- I schedule a job to run every 15 minutes, starting at 00:00:00.
- At 00:00:01 a request hits my WordPress site, it see's that I've got a
cron task that needs running. WordPress spawns a process to run that job.
- At 00:00:02 the loopback HTTP request WordPress has made hits PHP and
the cron task is run. The task takes 2 seconds to run. At 00:00:04
WordPress notices that it's a recurring job, it schedules the job to run
again - `$scheduled_time + $interval` = `00:15:00` - in 14m56s
- A bunch of HTTP requests hit a caching plugin, WordPress never loads.
- At 00:14:55 another request hits WordPress, no scheduled jobs need
running.
- A bunch of HTTP requests hit a caching plugin, WordPress never loads.
- At 00:16:30 the next HTTP request hits WordPress, WordPress see's that
a job should've run at `00:15:00`, it spawns cron via HTTP loopback. It's
been 16m24s since the last cron ran. ***Cron runs late***
- At 00:16:32 the cron task runs, it takes 30s this time due to a slow
network. At 00:17:02 the task has finished and WordPress schedules the
task to run again - `$scheduled_time + $interval` = `00:30:00` - in 12m58s
- A bunch of HTTP requests hit a caching plugin, WordPress never loads.
- At 00:30:03 the next HTTP request hits WordPress, WordPress see's that
a job should've run at `00:30:00`, it spawns cron via HTTP loopback. It's
been 13m01s since the last cron ran. ***Cron runs "early"***
- At 00:30:04 the cron task runs, it takes 1s. At 00:30:05 the task has
finished and WordPress schedules the task to run again - `$scheduled_time
+ $interval` = `00:45:00` - in 14m:55s
.. etc.
In order to improve cron spawning, some people have been known to run a
real cron task which hits `site.com/wp-cron.php` regularly - however this
has the downside that it can cause cron tasks to double up (as it bypasses
the WordPress cron locks).
There also exist external cron daemons which can be used to run tasks more
regularly, such as Cavalcade.
But the best option here, is to simply expect that the cron task will
never run on the exact schedule, it may run faster or slower depending on
when cron tasks are scheduled and the amount of visitors to WordPress - If
no-one visits WordPress, the cron jobs will never even run for example.
It's also possible that the job may run multiple times if the job takes
too long to finish, as WordPress may think the cron task failed to
execute.
If you wish for your cron tasks to run `at least 15 minutes after the time
the last job finished` you may wish to consider not using a recurring cron
task, and instead schedule a task to run in 15 minutes from now at the end
of your job, for example:
{{{
add_action( "init", "job_setup" );
function job_setup() {
if ( ! wp_next_scheduled( 'my_job' ) ) {
wp_schedule_single_event( "my_job", time() );
}
}
add_action( "my_job_name", "job_callback" );
function job_callback() {
// do stuff that takes 1s ~ 15 minutes
// ...
// Schedule this to run again in 15+ minutes time that his job finished
at
wp_schedule_single_event( "my_job", time() + 15 * 60 * 60 );
}
}}}
I'd recommend that you always check if the job is scheduled though and not
just do it on activation, as the job may fail or PHP timeout and it never
gets to the reschedule event.
I'm marking this as `worksforme` as it seems like it's working as expected
for me, I hope this reply has helped you understand what you're most
likely seeing.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/42866#comment:1>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list