I have a custom post type (‘my_cpt’) and upon save_post_my_cpt I need to possibly make a large number of modifications to other posts (depending on the state of the post, e.g., post_status, post_meta values and terms from custom taxonomy). These other modifications might need to be made in other blogs in a multisite. Hence, the function called on save_post_my_cpt might take up to a minute or so to complete execution…which isn’t very “user friendly” for the admin user doing the content changes.

I’m setting things up so that these other modifications happen via WP Cron. So I have:

add_action ('save_post_my_cpt', 'save_cpt') ;

function
save_cpt ($post_id)
{
    if (defined ('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return ;
        }

    // do stuff related to saving post meta, etc
    // e.g., update_post_meta ($post_id, '_some_meta_name', $_REQUEST['some_meta_name'], true) ;

    // schedule an event to do the modifications of other posts
    // see below for question related to the time this cron job will be scheduled
    $time = time () ;
    wp_schedule_single_event ($time, 'my_cron_hook', array ($post_id)) ;

    return ;
}

add_action ('my_cron_hook', 'cron_func') ;

function
cron_func ($post_id)
{
    $post = get_post ($post_id) ;

    // get_blogs_that_might_need_to_be_modified() returns an array of blog_id's that
    // MIGHT have other posts related to $post that need to be modified

    // get_posts_in_that_blog_that_need_to_be_modified() returns an array of posts
    // related to $post that need to be modified

    // modify_post() returns a modified version of a related post based on the
    // current state of $post

    // the details of these functions aren't relevant to this question
    foreach (get_blogs_that_might_need_to_be_modified ($post) as $blog_id) {
        switch_to_blog ($blog_id) ;

        foreach (get_posts_in_that_blog_that_need_to_be_modified ($post) as $other_post) {
            $other_post = modify_post ($post) ;
            wp_update_post ($other_post) ;
            }

        restore_current_blog () ;
        }
}

Hopefully, everyone is with me up to this point. My question has to do with the time at which I should schedule this 1 time cron job.

If I schedule the cron job to run “immediately” (as in the code above), can I be assured that by the time cron_func() is called that ALL of the DB updates related to the saving of my CPT will have completed (since the funcs called in cron_func() will need to read the modified state of $post_id)?

Scheduling the event to run “immediately” seems to work fine in my local development environment (where I’m the only one hitting the site).

I’m wondering if I’ll likely have any problems doing things this way when the site is running in a heavy activity production environment (i.e., with a number of admin users simultanously editing content on the back end, while a fair number of end-users are hitting the front end)

Two alternatives I’m considering:

  1. add some offset to time() when scheduling the event?
    1. e.g., schedule it to run 1 minute later
    2. if I need to do this, any guesses as to how long I should wait
  2. gather all of the info I need in save_cpt() and pass it in the $args param to wp_schedule_single_event()
    1. I would prefer not to go this route, as gathering that info could itself take a while, which would slow things down for the admin user
    2. is there “expense” (i.e., memory/etc) in passing a large amount of info to a job via cron?

Are there any other considerations that I should be accounting for? For example, what is likely the happen when:

  1. admin user A edits post X, which schedules the cron job
  2. before that cron job finishes, admin user B makes another edit to post X

1 Answer
1

If I schedule the cron job to run “immediately” (as in the code
above), can I be assured that by the time cron_func() is called that
ALL of the DB updates related to the saving of my CPT will have
completed (since the funcs called in cron_func() will need to read the
modified state of $post_id)

Yes. save_post hook is fired after the post has been actually saved. So, the cron_func will get the modified state of the post. You don’t need any alternative for this.

Are there any other considerations that I should be accounting for?
For example, what is likely the happen when:

  1. admin user A edits post X, which schedules the cron job before that
    cron job finishes,
  2. admin user B makes another edit to post X

If the cron job take some time, it’s very possible to encounter such an issue. To solve this issue, you might raise a flag(it can be a post meta) when creating the cron task and clear the flag when cron task finishes. You might want to disable editing of the post as long as the flag is present for a post.

Leave a Reply

Your email address will not be published. Required fields are marked *