Skip to content

Backgrounds

How-to Guides

Technical References

Code Quality and Best Practices /

Write asynchronous publishing actions

Often when a post is published, there’s a number of actions associated with that publication. Some of those actions can take a while to perform, for example syndicating content out to sibling sites, pushing to social media, etc.

On VIP Go you can offload actions to be processed asynchronously on the cron infrastructure for your site when a post is published or transitions status. Offloading actions reduces the processing time required for your publish action, which makes for a much faster publishing experience.

How to offload actions

Offloading an action on publish for asynchronous processing is as simple as changing the publish action hook to one of our async_ equivalents. The hooks we have available for asynchronous processing are:

  • async_transition_post_status, the asynchronous equivalent of transition_post_status (core hook docs)
  • async_{$old_status}_to_{$new_status}, the asynchronous equivalent of {$old_status}_to_{$new_status} (core hook docs)
  • async_{$new_status}_{$post->post_type}, the asynchronous equivalent of {$new_status}_{$post->post_type} (core hook docs)

This example splits off some functionality to be processed as the post is published, and some longer running functionality to be processed asynchronously:

/**
 * Runs when a post of type `post` is published.
 */
function my_post_publish_actions() {
    // This function performs quick actions,
    // and things which must happen immediately
}
add_action( 'publish_post', 'my_post_publish_actions' );
 
/**
 * Runs asynchronously, when a post of type `post` is published.
 */
function my_slower_post_publish_actions() {
    // This function performs slower actions,
    // like syndication and other longer 
    // running tasks
}
add_action( 'async_publish_post', 'my_slower_post_publish_actions' );

The code that powers our asynchronous offloading functionality works by scheduling an immediate cron event to be processed on our dedicated cron infrastructure, during which these async_* action hooks are called.

Skipping async actions

There may be cases where you do not need to queue actions for specific post types (e.g. private post types with high volumes of activity). You can skip queueing async actions for them using the wpcom_async_transition_post_status_schedule_async filter.

The following snippet skips async transition actions for the all posts with the x-transactions post type:

add_filter( 'wpcom_async_transition_post_status_schedule_async', function( $value, $args ) {
    if ( 'x-transactions' === get_post_type( $args['post_id'] ) ) {
        $value = false;
    }
    return $value;
}, 10, 2 );

Caution

The asynchronous actions will be processed on separate infrastructure to the web requests. This means that the asynchronous action will not have access to anything that has been placed in the global context, or access files placed in a system tmp directory during a previous request, etc.

Caution

The events are not guaranteed to fire in the order they occur because they are processed concurrently. This means that if you trash a post and then untrash it, the async events for those actions may fire out of order or at the same time. This means that if you need to take action based on the status of a post, you should verify it using get_post( $post->ID )->post_status before doing so.

Last updated: April 09, 2021