Make WordPress Core

Opened 6 years ago

Closed 5 years ago

Last modified 5 years ago

#42660 closed defect (bug) (invalid)

Single event scheduler

Reported by: skarabeq's profile skarabeq Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.9
Component: Cron API Keywords: reporter-feedback
Focuses: Cc:

Description

When I set single event for wp_cron for example 2017-11-22 00:00:00 it is executed than more one time. I think it should be only one time and if wordpress doesn't have users at the same time first user who open wordpress site will triggered wp cron. Example 0 users 2017-11-22 00:00:00 on website and wp_cron is not executed , 2017-11-22 00:15:27 - 1 user on wordpress website and cron is executed only one time.

Change History (21)

#1 in reply to: ↑ description @1naveengiri
6 years ago

@skarabeq What code for cron setup you used, can you paste it here to understand it better?

Replying to skarabeq:

When I set single event for wp_cron for example 2017-11-22 00:00:00 it is executed than more one time. I think it should be only one time and if wordpress doesn't have users at the same time first user who open wordpress site will triggered wp cron. Example 0 users 2017-11-22 00:00:00 on website and wp_cron is not executed , 2017-11-22 00:15:27 - 1 user on wordpress website and cron is executed only one time.

#2 @skarabeq
6 years ago

<?php
$next_run = strtotime('2017-11-22 10:00');
wp_clear_scheduled_hook('single_action');
wp_schedule_single_event($next_run, 'single_action');
Last edited 6 years ago by skarabeq (previous) (diff)

#3 @dd32
6 years ago

  • Component changed from General to Cron API
  • Focuses performance removed
  • Keywords reporter-feedback added

Unfortunately, the WordPress cron api isn't guaranteed to only run once, code should expect that it's possible for it to happen - however it's extremely unlikely to happen.
We've improved things greatly over what it used to be #17462 & #19700, I don't think I've heard of major complaints since then.
Running an external cron implementation such as Cavalcade can help, especially when the tasks are long running.

Given your code in the above comment, how are you running that? Is there a chance that the job is simply being scheduled twice?
What do you see if you run it like so: Do you get multiple timestamps being passed as the first parameter?

wp_schedule_single_event( time(), 'single_action', array( microtime(1) ) );

#4 follow-up: @skarabeq
6 years ago

@dd32 , no it is not working as well

<?php
wp_schedule_single_event( time(), 'single_action', array( microtime(1) ) );

And when I open https://wptest.dev/wp-cron.php?doing_wp_cron via crontab 5 times I got 5 executed cron events. It must be only once.

Last edited 6 years ago by skarabeq (previous) (diff)

#5 @skarabeq
6 years ago

  • Severity changed from normal to major

#6 in reply to: ↑ 4 @dd32
6 years ago

  • Severity changed from major to normal

Replying to skarabeq:

And when I open https://wptest.dev/wp-cron.php?doing_wp_cron via crontab 5 times I got 5 executed cron events. It must be only once.

You're bypassing the cron locks by doing that, and as a result, the cron task being fired multiple times is expected.

The cron should be only triggered by calling spawn_cron().
If you're using an external trigger for cron tasks by calling the cron url directly then you'll need to handle it yourself some other way.

I'm going to mark the ticket as invalid as it sounds like this is purely due to you triggering the cron manually, if you can experience cron tasks running multiple times, via spawn_cron() (Which is what WordPress uses) feel free to re-open the ticket with detailed information we can use to duplicate it.

#7 @skarabeq
6 years ago

  • Severity changed from normal to major

Can I run event once via code ?

#8 @skarabeq
6 years ago

@dd32 I'm not sure you are right. Same as result when I set cron

<?php
wp_schedule_single_event( time(), 'single_action', array( microtime(1) ) );

and then open base url https://wptest.dev or open https://wptest.dev/wp-admin wp cron is triggered.
I think doesn't matter what I open for triggered wp cron. So If I have 100 users and they open home page, the wordpress will triggered 100 times this single event wp cron. It should be only once.

#9 @ocean90
6 years ago

  • Severity changed from major to normal

That's expected behaviour when use wp_schedule_single_event() and time(). You have to use a fixed time and/or register it only once to schedule the event only once. You also might want to use wp_next_scheduled().

<?php
if ( ! wp_next_scheduled( 'single_action' ) ) {
        wp_schedule_single_event( strtotime( '2017-11-22 11:00' ), 'single_action' );
}

#10 follow-up: @skarabeq
6 years ago

  • Severity changed from normal to major

@ocean90 with this code:

<?php
if ( ! wp_next_scheduled( 'single_action' ) ) {
        wp_schedule_single_event( strtotime( '2017-11-22 11:00' ), 'single_action' );
}

isn't works like as expect. Still triggered event on every refresh on website (doesn't matter where I'm)

This ticket was mentioned in Slack in #core by skarabeq. View the logs.


6 years ago

#12 in reply to: ↑ 10 @dd32
6 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to invalid
  • Severity changed from major to normal
  • Status changed from new to closed

Replying to skarabeq:

@ocean90 with this code:

<?php
if ( ! wp_next_scheduled( 'single_action' ) ) {
        wp_schedule_single_event( strtotime( '2017-11-22 11:00' ), 'single_action' );
}

isn't works like as expect. Still triggered event on every refresh on website (doesn't matter where I'm)

I think what is happening here is:

  • Pageload 1: See's there's no single_action scheduled, so queues it up. Later in the pageload it sees there's crons that need running, so it spawns the cron process.
    • Cron pageload runs in background. removes cron entry.
  • Pagelaod 2: The cron run has already processed the cron and removed its entry from the database, so wp_next_scheduled( 'single_action' ) is once again false, so it queues it up again to run
    • Cron pageload runs in the background again

rinse repeat.

In your case, you should -conditionally- call wp_schedule_single_event() when a certain circumstance is true (For example, if ( isset( $_POST['schedule-the-cron'] ) ) { wp_schedule_single_event( time(), 'single_action' ); }).

This is a hastily written, and insecure, but here's an example plugin which shows an implementation where the cron only fires once, in response to a user action triggering it to run:
https://gist.github.com/dd32/d1091e4f6316dba126814b5d3ce559bb

I hope this helps set you on the right direction.
I'm marking this ticket as invalid as there's nothing which can be used to point to a core bug, discussion can still occur while the ticket is closed, please do not re-open the ticket unless you have information which can be used to reproduce a bug in core.

#13 @skarabeq
6 years ago

@dd32 , this is good solution, but when this default function wp_schedule_single_event isn't works as a single event , his name is wrong. My solution is similar to yours solution in gist.

#14 @dd32
6 years ago

I can see where it may be confusing, It schedules a single (once-off) task to run, this is in comparison to wp_schedule_event() which schedules a recurring (non-single) event which re-queues itself.

#15 @skarabeq
6 years ago

wp_schedule_single_event is run more than one time when you have no additional check. For me single event is mean only one time run without additional checks.

#16 @skarabeq
5 years ago

  • Resolution invalid deleted
  • Severity changed from normal to major
  • Status changed from closed to reopened

#17 @skarabeq
5 years ago

This bug still isn't solved! What is the status of solution ?

This ticket was mentioned in Slack in #core by skarabeq. View the logs.


5 years ago

#19 @dd32
5 years ago

  • Resolution set to invalid
  • Severity changed from major to normal
  • Status changed from reopened to closed

As stated

I can see where it may be confusing, It schedules a single (once-off) task to run, this is in comparison to wp_schedule_event() which schedules a recurring (non-single) event which re-queues itself.

Nothing here indicates a bug.

#20 @skarabeq
5 years ago

  • Resolution invalid deleted
  • Status changed from closed to reopened

@dd32 What is not clear ? I clearly explained more than one times when I use wp_schedule_single_event it is running more than one time. If I have one user on the website and he refresh 10 times web page the cron will be executed 10 times, if I have 100 users with 10 refreshes on website the cron will be executed 1000 times. Could you please check this in details, because this is bug!

Again I will paste my simple code:

<?php
$time = strtotime(date('Y-m-d 00:00:00', strtotime('next Tuesday'))); 
 wp_schedule_single_event($time, 'hook_of_cron_job');


#21 @mariovalney
5 years ago

  • Resolution set to invalid
  • Status changed from reopened to closed

Hi @skarabeq how are you?

A event scheduled with wp_schedule_single_event will run just one time for each time you scheduled it (as @dd32 explained here).

You have to make sure you will not call wp_schedule_single_event function after the event runned.

If you want a event run just really once (and never again) the best way is to run wp_schedule_single_event in a action will run just once (like activating a plugin). If it's not possible, another solution would be add a entry in database (before it run to avoid parallel events and after it run to say "it's done: never schedule this again").

P.S: A video with a test you can do to check it's not a Core bug.

Last edited 5 years ago by mariovalney (previous) (diff)
Note: See TracTickets for help on using tickets.