Search code examples
phpwordpresscrontimeout

WordPress: Auto save posts every night with scheduled event


I want to save every post at night with a scheduled event. Because we've a lot of posts, I want to split the posts in chunks of 25.

This is my current code for that:

function autosave_posts() {
    // Set up query arguments
    $args = array(
        'post_type'      => 'post',
        'post_status'    => 'publish',
        'posts_per_page' => 25,
        'orderby'        => 'ID',
        'order'          => 'ASC',
        'paged'          => 1, // Start with first page
    );

    // Loop through posts until all have been updated
    while ( $posts = new WP_Query( $args ) ) {
        if ( $posts->have_posts() ) {
            while ( $posts->have_posts() ) {
                $posts->the_post();
                wp_update_post( array( 'ID' => get_the_ID() ) );
            }
            wp_reset_postdata();

            // Increment the paged argument to get the next set of posts
            $args['paged']++;
        } else {
            // There are no more posts, so we're done
            break;
        }
    }
}

// Schedule the event if it doesn't already exist
if ( ! wp_next_scheduled( 'autosave_posts' ) ) {
    wp_schedule_event( strtotime( '04:00:00' ), 'daily', 'autosave_posts' );
}

// Hook the function to the scheduled event
add_action( 'autosave_posts', 'autosave_posts' );

I tested it with a time 2 minutes in the future. But unfortunately the posts were not saved.

I checked the cron events with Cron Crontrol and saw that the event was in the list. So I runned it.

Some of the posts were saved. But not all of them because the maximum execution time of 60 seconds for the function were exceeded.

I added sleep(5) after the while loop. But the problem with the maximum execution time is still there.

Now I've two questions:

  1. Is the function correct and would run? Was my "time in the future" wrong? I'm not sure which time the function wp_schedule_event uses.
  2. Is there a way to prevent the problem with the maximum execution time? Can I split the function in any way? I thought the 25 post chunks were enough

Solution

  • Try calling set_time_limit(60) on the line after your while statement. It will reset the time limit to a minute for each time through your loop, reducing the chance of a timeout.

    Avoid sleep(). It ties up a scarce web-server process for no good reason. And, sleeps don't count against the time limit.

    But, some hosts impose an overall, non-resettable time limit. In that case you will need to reduce your batch size from 25 to something smaller.

    You didn't say why you do this. There may be a much more efficient way to do what you need to do. But it's hard to give you specific advice without knowing why.