Make WordPress Core

Changeset 60925


Ignore:
Timestamp:
10/12/2025 09:40:08 PM (7 months ago)
Author:
peterwilsoncc
Message:

Cron API: Spawn cron jobs on shutdown hook.

Modifies wp_cron() to register the spawning of cron jobs on the shutdown hook rather than the wp_loaded hook.

The loopback request made while spawning cron jobs is intended to be non-blocking, however in some circumstances that isn't the case and the spawning will increase the time to first byte.

Props westonruter, pmbaldha, mukesh27.
Fixes #63858.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/cron.php

    r60653 r60925  
    973973
    974974/**
    975  * Registers _wp_cron() to run on the {@see 'wp_loaded'} action.
    976  *
    977  * If the {@see 'wp_loaded'} action has already fired, this function calls
    978  * _wp_cron() directly.
    979  *
    980  * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
    981  * value which evaluates to FALSE. For information about casting to booleans see the
    982  * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use
    983  * the `===` operator for testing the return value of this function.
     975 * Registers _wp_cron() to run on the {@see 'shutdown'} action.
     976 *
     977 * The spawn_cron() function attempts to make a non-blocking loopback request to `wp-cron.php` (when alternative
     978 * cron is not being used). However, the wp_remote_post() function does not always respect the `timeout` and
     979 * `blocking` parameters. A timeout of `0.01` may end up taking 1 second. When this runs at the {@see 'wp_loaded'}
     980 * action, it increases the Time To First Byte (TTFB) since the HTML cannot be sent while waiting for the cron request
     981 * to initiate. Moving the spawning of cron to the {@see 'shutdown'} hook allows for the server to flush the HTML document to
     982 * the browser while waiting for the request.
    984983 *
    985984 * @since 2.1.0
    986985 * @since 5.1.0 Return value added to indicate success or failure.
    987986 * @since 5.7.0 Functionality moved to _wp_cron() to which this becomes a wrapper.
    988  *
    989  * @return false|int|void On success an integer indicating number of events spawned (0 indicates no
    990  *                        events needed to be spawned), false if spawning fails for one or more events or
    991  *                        void if the function registered _wp_cron() to run on the action.
    992  */
    993 function wp_cron() {
    994     if ( did_action( 'wp_loaded' ) ) {
    995         return _wp_cron();
    996     }
    997 
    998     add_action( 'wp_loaded', '_wp_cron', 20 );
     987 * @since 6.9.0 The _wp_cron() callback is moved from {@see 'wp_loaded'} to the {@see 'shutdown'} action; the function always returns void.
     988 */
     989function wp_cron(): void {
     990    if ( doing_action( 'shutdown' ) ) {
     991        _wp_cron();
     992    } else {
     993        add_action( 'shutdown', '_wp_cron' );
     994    }
    999995}
    1000996
  • trunk/tests/phpunit/tests/cron.php

    r58164 r60925  
    13311331        $this->assertSame( 'could_not_set', $unscheduled->get_error_code() );
    13321332    }
     1333
     1334    /**
     1335     * @ticket 63858
     1336     *
     1337     * @covers ::wp_cron
     1338     */
     1339    public function test_wp_cron_before_shutdown() {
     1340        remove_all_actions( 'shutdown' );
     1341        wp_cron();
     1342        $this->assertSame( 10, has_action( 'shutdown', '_wp_cron' ), 'Expected _wp_cron() to be scheduled for shutdown.' );
     1343    }
     1344
     1345    /**
     1346     * @ticket 63858
     1347     *
     1348     * @covers ::wp_cron
     1349     */
     1350    public function test_wp_cron_already_at_shutdown() {
     1351        remove_all_actions( 'shutdown' );
     1352        add_action( 'shutdown', 'wp_cron' );
     1353        do_action( 'shutdown' );
     1354        $this->assertFalse( has_action( 'shutdown', '_wp_cron' ), 'Expected wp_cron() to not add _wp_cron() to run at shutdown.' );
     1355    }
    13331356}
Note: See TracChangeset for help on using the changeset viewer.