Make WordPress Core


Ignore:
Timestamp:
03/16/2019 06:41:23 AM (6 years ago)
Author:
peterwilsoncc
Message:

Cron: Ensure identical single events aren't scheduled less than 10min apart.

Improves the logic in wp_schedule_single_event() to ensure an identical event is not scheduled within ten minutes.

This moves the logic for checking for identical events to be self contained rather than relying on wp_next_scheduled() as this fails to account for events with a past timestamp when wp-cron fails to trigger or for multiple identical events being scheduled already.

Props bodohugobarwich.
Fixes #44818.

File:
1 edited

Legend:

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

    r44694 r44917  
    8080    }
    8181
    82     // Don't schedule a duplicate if there's already an identical event due within 10 minutes of it
    83     $next = wp_next_scheduled( $hook, $args );
    84     if ( $next && abs( $next - $timestamp ) <= 10 * MINUTE_IN_SECONDS ) {
     82    /*
     83     * Check for a duplicated event.
     84     *
     85     * Don't schedule an event if there's already an identical event
     86     * within 10 minutes.
     87     *
     88     * When scheduling events within ten minutes of the current time,
     89     * all past identical events are considered duplicates.
     90     *
     91     * When scheduling an event with a past timestamp (ie, before the
     92     * current time) all events scheduled within the next ten minutes
     93     * are considered duplicates.
     94     */
     95    $crons     = (array) _get_cron_array();
     96    $key       = md5( serialize( $event->args ) );
     97    $duplicate = false;
     98
     99    if ( $event->timestamp < time() + 10 * MINUTE_IN_SECONDS ) {
     100        $min_timestamp = 0;
     101    } else {
     102        $min_timestamp = $event->timestamp - 10 * MINUTE_IN_SECONDS;
     103    }
     104
     105    if ( $event->timestamp < time() ) {
     106        $max_timestamp = time() + 10 * MINUTE_IN_SECONDS;
     107    } else {
     108        $max_timestamp = $event->timestamp + 10 * MINUTE_IN_SECONDS;
     109    }
     110
     111    foreach ( $crons as $event_timestamp => $cron ) {
     112        if ( $event_timestamp < $min_timestamp ) {
     113            continue;
     114        }
     115        if ( $event_timestamp > $max_timestamp ) {
     116            break;
     117        }
     118        if ( isset( $cron[ $event->hook ][ $key ] ) ) {
     119            $duplicate = true;
     120            break;
     121        }
     122    }
     123
     124    if ( $duplicate ) {
    85125        return false;
    86126    }
     
    108148    }
    109149
    110     $key = md5( serialize( $event->args ) );
    111 
    112     $crons = _get_cron_array();
    113150    $crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
    114151        'schedule' => $event->schedule,
Note: See TracChangeset for help on using the changeset viewer.