[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