How to make sure that only one wp_cron() runs at a time?

Yes, it is possible…

And to be honest, it’s often very important to do this… WP Scheduler sometimes tends to cause problems, when cron tasks are long…

So how I solve this problem?

I use Transients API to implement semaphores…

Here’s the code:

if ( ! wp_next_scheduled( 'my_task_hook' ) ) {
  wp_schedule_event( time(), 'hourly', 'my_task_hook' );
}

add_action( 'my_task_hook', 'my_task_function' );

function my_task_function() {
  // if some other my_task is already running, stop
  if ( get_transient( 'my_task_function_semaphore' ) ) return;

  // set semaphore for 5 minutes
  set_transient( 'my_task_function_semaphore', true, 5*60 );

  // DO YOUR STUFF

  delete_transient( 'my_task_function_semaphore' );
}

Why do I use transients in this case? Because:

  • They’re part of WP.
  • They’re easy to use and efficient.
  • They won’t cause deadlocks. Let’s say my cron task can get killed (some error may occur, or it runs too long and gets killed, and so on). In such case it won’t delete semaphore, so all future tasks won’t work. Using transients solves this problem, because after some time transient will be deleted.

And what if there are many different actions to do?

So let’s say there are many different cron tasks, that should never run in same time, but we still want them all to run…

If we use the solution with semaphore and use only one semaphore for all of these tasks, then some of them may never run. So what to do then?

In such case you should change your thinking. You don’t have some independent tasks, but a queue of tasks to do. So you should implement it in this way.

So:

  1. You add some kind of queue (you can use an array and store it as option, or add a custom DB table).
  2. You use your currently WP cron hourly event to add tasks to queue.
  3. You add second WP cron tasks which runs much more often and it “eats” tasks from queue one by one. This “eater” task should use semaphore to ensure that only one task runs at a moment.

Leave a Comment