#28213 closed defect (bug) (fixed)
wp_schedule_single_event() prevents scheduling a future event when it should not
Reported by: |
|
Owned by: |
|
---|---|---|---|
Milestone: | 4.1 | Priority: | normal |
Severity: | normal | Version: | |
Component: | Cron API | Keywords: | has-patch |
Focuses: | Cc: |
Description
[9181] added some defensive code to wp_schedule_single_event() suggested in #6966, to stop scheduling duplicate events in the event of a flood.
That patch did solve the intended problem, but also introduced some unintended behaviour. If an event is currently executing, or is past due but hasn't completed for some reason, it will refuse to schedule a similar event at any future time - even if you attempt to schedule something weeks ahead.
This turned up when testing the Akismet plugin: in the event that servers are unreachable, the cron_recheck() hook attempts to re-schedule itself for 6 hours in the future. But wp_schedule_single_event() rejects it because there is already a similar event scheduled a few seconds in the past (itself).
That wasn't the intent of the original fix, and I think it should be considered a bug. I'd suggest that wp_schedule_single_event() should only reject an event as a duplicate if there is already a similar event scheduled within 10 minutes of the given timestamp.
While testing this I discovered there's a bug in the associated unit test, Tests_Cron::test_not_duplicate_event(). It schedules two future events and checks that they are both there. wp_next_scheduled() returns the wrong event (it returns the later event, not the next), but the test as written incorrectly accepts this as expected behaviour.
Attachments (1)
Change History (6)
#2
@
11 years ago
I wonder if this is what I'm running into. I am running a cron job every minute that does a network operation. This network operation has a percentage chance of timing out or not completing by the time next cron event next minute is in theory scheduled to run.
Result is that my cronjob arbitrarily simply disappears from the list. I can still see my custom 1 minute schedule in Cron Debug Bar, so I know my uber-simple cron plugin is setting things up right. But unless I re-cycle plugin activation, my cron job will never run again.
Uber-simple plugin for reference:
register_activation_hook( __FILE__, array( "MyClass", "cron_setup" ) ); register_deactivation_hook( __FILE__, array( "MyClass", "cron_remove" ) ); MyClass::on_load(); class MyClass { static function on_load() { add_filter( "cron_schedules", array( __CLASS__, "ny_minute" ) ); add_action( "myclass_resend_failed", array( __CLASS__, "resend_failed" ) ); } static function cron_setup() { wp_schedule_event( time(), "minutes_1", "myclass_resend_failed" ); } static function cron_remove() { wp_clear_scheduled_hook( "myclass_resend_failed" ); } static function ny_minute( $schedules ) { $schedules[ "minutes_1" ] = array( "interval" => 60, "display" => "Once every NY minute" ) return $schedules; } static function resend_failed() { # do magic, but occasionally timeouting network stuff here }
#4
@
10 years ago
- Owner set to wonderboymusic
- Resolution set to fixed
- Status changed from new to closed
In 29939:
The patch fixes the bug, and the unit test, and adds a second test to cover the reverse order.
Thanks @cfinke for suggesting the fix.