Run Scheduled WP Cron Tasks Right Away in WordPress

I’m trying to run WordPress cron tasks right after scheduling some action events. Usually WordPress Cron at least takes one another page load to trigger scheduled tasks. I’m trying to do it right away. I’ve almost managed to do it as shown in the below code.

/* Plugin Name: Sample Cron Immediate Execution  */

add_action('admin_menu', 'sample_cron_immediate_execution');
function sample_cron_immediate_execution() {
    add_options_page(
        'Sample Cron Immediate Execution', 
        'Sample Cron Immediate Execution', 
        'manage_options',
        'sample_cron_immediate_execution', 
        'sample_cron_immediate_execution_admin');
}
function sample_cron_immediate_execution_admin() {
    ?>
    <div class="wrap">
    <?php
        wp_schedule_single_event(time(), 'my_action1');
        wp_schedule_single_event(time(), 'my_action2');
        $cron_url = site_url( 'wp-cron.php?doing_wp_cron=0');
        wp_remote_post( $cron_url, array( 'timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters( 'https_local_ssl_verify', true ) ) );
        echo 'cron tasks should be executed by now.';
    ?>
    </div>
    <?php
}

add_action('my_action1', 'myeventfunc1'); 
function myeventfunc1() {
    sleep(10); // assuming it's a heavy task 
    sample_log(date('l jS of F Y h:i:s A'), __DIR__ . '/myevent1_log.html');
}

add_action('my_action2', 'myeventfunc2');    
function myeventfunc2() {
    sleep(10); // assuming it's a heavy task 
    sample_log(date('l jS of F Y h:i:s A'), __DIR__ . '/myevent2_log.html');
}

function sample_log($time, $file) {
    file_put_contents($file, $time . '<br />', FILE_APPEND);
}

The problem is that when one of the tasks is heavy, it seems WordPress does not complete all tasks in one call of wp-cron.php. I’m guessing that the $_GET value, doing_wp_cron, is something to do with it as I view the code of the core file,

Read More

One of the comments says

Use global $doing_wp_cron lock otherwise use the GET lock. If no lock, trying grabbing a new lock.

I don’t fully understand what this is about. What I’d like to do is to execute multiple scheduled tasks right away without requiring to open another page regardless of the heaviness of the tasks.

Thanks for your information.

Related posts

Leave a Reply

4 comments

  1. Why rebuild the native scheduler? This should work:

    function my_job() {
        // heavy lifting
    }
    add_action( 'my_hook', 'my_job' );
    
    wp_schedule_single_event( time(), 'my_hook', array( 'my_arg' ) );
    spawn_cron();
    
  2. This should do the job.

    <?php
        /* Plugin Name: Sample Cron Immediate Execution  */
    
        add_action('admin_menu', 'sample_cron_immediate_execution');
        function sample_cron_immediate_execution() {
            add_options_page(
                'Sample Cron Immediate Execution', 
                'Sample Cron Immediate Execution', 
                'manage_options',
                'sample_cron_immediate_execution', 
                'sample_cron_immediate_execution_admin');
        }
        function sample_cron_immediate_execution_admin() {
            ?>
            <div class="wrap">
            <?php
                $cron_url = site_url( '?custom_cron=myeventfunc1');         
                wp_remote_post( $cron_url, array( 'timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters( 'https_local_ssl_verify', true ) ) );
                $cron_url = site_url( '?custom_cron=myeventfunc2');         
                wp_remote_post( $cron_url, array( 'timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters( 'https_local_ssl_verify', true ) ) );
                echo 'cron tasks should be executed by now.';
            ?>
            </div>
            <?php
        }
    
        add_action('init', 'run_customcron');
        function run_customcron() 
        {
            if (isset($_GET['custom_cron']))
            {
                call_user_func($_GET['custom_cron']);
            }
        }
    
        function myeventfunc1() {
            sleep(10); // assuming it's a heavy task 
            sample_log(date('l jS of F Y h:i:s A'), __DIR__ . '/myevent1_log.html');
        }
    
        function myeventfunc2() {
            sleep(10); // assuming it's a heavy task 
            sample_log(date('l jS of F Y h:i:s A'), __DIR__ . '/myevent2_log.html');
        }
    
        function sample_log($time, $file) {
            file_put_contents($file, $time . '<br />', FILE_APPEND);
        }
    
  3. Try to change timeout to 30 seconds.

    wp_remote_post( $cron_url, array( 'timeout' => 30, 'blocking' => false, 'sslverify' => apply_filters( 'https_local_ssl_verify', true ) ) );
    
  4. I don’t quite understand why you’d want to use cron if you’re only scheduling a single event and want it to run right away–why wouldn’t you just execute the action?

    do_action('my_action1');
    do_action('my_action2');
    

    WordPress automatically runs any overdue crons every time the page is accessed anyway, so I don’t see justification for manually calling wp-cron.

    Regarding your

    when one of the tasks is heavy, it seems WordPress does not complete all tasks in one call of wp-cron.php

    comment, know that PHP, by default, kills execution of a script (including WordPress crons) if it takes longer than 30 seconds. So say you have 5 crons scheduled, each taking exactly 9 seconds to run. The first 3 will run, but the last two will not (PHP will die shortly after starting the 4th). I’ve used PHP’s set_time_limit function with good results, to allow my server to execute a VERY large cURL request within a wordpress cron.

    A couple more things:

    • cron is supposed to be asynchronous. You’re trying to make it synchronous, which could cause significant page load delays.
    • Be sure you call add_action before calling do_action