[wp-trac] [WordPress Trac] #63938: A feature to bulk schedule events

WordPress Trac noreply at wordpress.org
Fri Sep 5 18:35:50 UTC 2025


#63938: A feature to bulk schedule events
-------------------------+-----------------------------
 Reporter:  urlund       |      Owner:  (none)
     Type:  enhancement  |     Status:  new
 Priority:  normal       |  Milestone:  Awaiting Review
Component:  Cron API     |    Version:
 Severity:  normal       |   Keywords:
  Focuses:               |
-------------------------+-----------------------------
 I was playing around today with wp_schedule_single_event, and when
 scheduling a bunch of events (1000) the traditional way if scheduling
 becomes rather slow. So instead I made a solution for a
 wp_schedule_bulk_events function.

 I'd like to submit this to WP core if you'd like, but not sure how :)

 I hope the rest speaks for itself. Let me know if you have any suggestions
 or adjustments.

 {{{#!php
 <?php
 /**
  * Schedule a bulk of events.
  *
  * @param int    $timestamp  Unix timestamp (UTC) for when to next run the
 event.
  * @param string $hook       Action hook to execute when the event is run.
  * @param array  $args       An array of arrays containing arguments to
 pass to the
  *                           hook's callback function. The array keys are
 ignored.
  * @param bool   $wp_error   Optional. Whether to return a WP_Error on
 failure. Default false.
  * @return bool|WP_Error True if event successfully scheduled. False or
 WP_Error on failure.
  */
 function wp_schedule_bulk_events(int $timestamp, string $hook, array
 $args, bool $wp_error = false)
 {
     // check if all arguments are arrays
     $is_array_args = array_reduce( $args, fn($carry, $item) => $carry &&
 is_array($item), true );

     // if not, schedule a single event
     if ( ! $is_array_args) {
         return wp_schedule_single_event( $timestamp, $hook, $args,
 $wp_error );
     }

     // get current cron events
     $bulk_value = $orig_value = get_option( 'cron', [] );

     // when updating the cron option, keep a copy of the original value
 (to skip update for now)
     $tmp_update_option = function ($new_value, $old_value) use
 (&$bulk_value) {
         $bulk_value = $new_value;
         return $old_value;
     };

     // when getting the cron option, return the modified value
     $tmp_get_option = function () use (&$bulk_value) {
         return $bulk_value;
     };

     // add filters from above
     add_filter( 'pre_update_option_cron', $tmp_update_option, 10, 2 );
     add_filter( 'pre_option_cron', $tmp_get_option, 10 );

     // add cron events
     foreach ( $args as $arg ) {
         wp_schedule_single_event( $timestamp, $hook, $arg, $wp_error );
     }

     // remove filters
     remove_filter( 'pre_update_option_cron', $tmp_update_option, 10, 2 );
     remove_filter( 'pre_option_cron', $tmp_get_option, 10 );

     // if the cron option was changed in the meantime, abort
     if ($orig_value !== get_option( 'cron', [] )) {
         return $wp_error ? new \WP_Error('wp_schedule_bulk_events_failed',
 __('Failed to verify bulk schedule cron events, value has changed',
 'wordpress')) : false;
     }

     // update cron option
     if ( ! update_option( 'cron', $bulk_value )) {
         return $wp_error ? new \WP_Error('wp_schedule_bulk_events_failed',
 __('Failed to update bulk schedule cron events', 'wordpress')) : false;
     }

     return true;
 }

 /**
  * The test
  */

 // args for test events
 $test_args = array_map( fn($i) => [$i], range(1, 1000) );
 $timestamp = time() + 3600;

 // test 1 - traditional scheduling
 $start_time = microtime(true);
 foreach ( $test_args as $test_arg ) {
     wp_schedule_single_event( $timestamp, 'test1', $test_arg );
 }

 echo "Traditional scheduling time: " . round( microtime(true) -
 $start_time, 5 ) . " seconds" . PHP_EOL;

 // test 2 - bulk scheduling
 $start_time = microtime(true);
 wp_schedule_bulk_events( $timestamp, 'test2', $test_args );

 echo "Bulk scheduling time: " . round( microtime(true) - $start_time, 5 )
 . " seconds" . PHP_EOL;

 }}}


 **Result:**
 Traditional scheduling time: 7.82431 seconds
 Bulk scheduling time: 0.02945 seconds

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/63938>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list