5

I recently noticed that in Heartbeat API js client there was added option for speed of ticks called "long polling" with 0 interval. I pretty much understand what they try to achieve but I'm confused about how to implement plugin using this feature.

For now every time my server received request from browser, hook was fired, data queried, response created and sent back to client. But with 0 interval, I should actually wait in my hook for some event being triggered and then create response, right?

Could somebody provide some simple code as example of this new feature?

  • 1
    Just looked that up out of curiosity. I've found a Make WordPress article, which links the term long-polling to Wikipedia. Maybe it helps. Aside from that I'm not that familiar with the heartbeat API, so I can't give you a sufficient answer, at least not at a heartbeat :) But from what I've read just now, I think long-polling might not actually be used, but no warranty on that. – Nicolai Sep 22 '14 at 12:56
  • 1
    Long polling isn't used due to unreliability of servers (see discussion in #23216). To clarify, is this a question on how to use the Heartbeat API or implement long-polling? – Stephen Harris Sep 22 '14 at 14:24
  • @StephenHarris This is a question about how to use 0 interval (named in javascript client file as "long-polling" and commented as experimental) in Heartbeat API. – user3562259 Sep 22 '14 at 14:50
7

The Hearbeat API works by periodically sending an XHR request to the server, with hooks available for WordPress/plug-ins/themes to attach data to be returned to the client. Once the data is returned, a new beat is scheduled. The speed (or 'pulse') of the heartbeat may be tempered, either server-side or client side in reaction to events (e.g. user inactivity).

Long polling

Long polling works in a similar way but (source: Wikipedia)

If the server does not have any information available for the client when the poll is received, instead of sending an empty response, the server holds the request open and waits for response information to become available. Once it does, the server immediately sends an HTTP/S response to the client, completing the open HTTP/S Request.

So rather than periodically sending requests and hoping we get something back, we send one request, and the server sends the data back when its ready. Once it does, we immediately initiate a new XHR request, hence the interval is 0.

Health warning

As mentioned in the question's comments, long polling is a 'latent' feature in WordPress. The Heartbeat API makes provision for it, without actually implementing it. The reasons for it not being implemented are covered in track ticket #23216, and I recommend you read the discussion.

In short however, the disadvantages/potential problems include:

  • Caching - Long poll requests load WordPress. Database queries (including options, posts etc) are cached. If your script is waiting for data to be changed, you'll need to mindful that you're not checking cached data which won't change unless you clear the cache.
  • Server settings - Long poll requests in this context can be thought of a (potentially) very very long page request. The example below kills itself after 20 seconds, but your host may kill it off long before that, rendering long polling fairly impotent.
  • Server resources - Each visitor will be tying up server resources, almost constantly.

For these reasons I recommend you only use it in a controlled environment (e.g. you control the server, and which plug-ins/themes are running). But with that level of control, you may want to consider using WebSockets instead.

Setting up long-polling

1. Setting the interval

First you need to set the interval to 'long-polling'. Effectively this means a 0 interval.

function wpse162220_heartbeat_settings( $settings ) {
    $settings['interval'] = 'long-polling';
    return $settings;
}
add_filter( 'heartbeat_settings', 'wpse162220_heartbeat_settings' );

2. Add a 'long-poll listener'

This is a callback which allows you to attach data to be returned to the client. Copying Nacin's example from the track ticket we have a 2-second period, and wait up to 20 seconds.

function wpse162220_poll() {

    for ( $i = 0; $i < 10; $i++ ) {

        $val = apply_filters( 'wpse162220_poll', array() );

        if ( ! empty($val) ) {
            echo json_encode($val);
            exit;
        }

        sleep(2);
    }

    echo '0';
    exit;
}

add_action( 'heartbeat_tick', 'wpse162220_poll' );
add_action( 'heartbeat_nopriv_tick', 'wpse162220_poll' ); 

3. (a) Attach data

This is a 'dummy' function which just waits until the third iteration of the loop in the previous section and then adds some data

function wpse162220_populate_data( $value ){
    static $counter = 0;

    $counter++;

    if( $counter == 3 ){
        $value['wpse162220'] = 'foobar';
    }

    return $value;

}
add_filter( 'wpse162220_poll', 'wpse162220_populate_data' );

3. (b) Display the received data

I've been lazy here and printed the javascript straight to the page. You would normally go through the whole rigmarole of registering & enqueueing a javascript file.

All this does is print the response to the console.

function wpse162220_print_javascript(){
    ?>  
    <script>
    jQuery(document).ready( function($) {
        $(document).on( 'heartbeat-tick.wpse162220', function( event, data ) {
            if ( data.hasOwnProperty( 'wpse162220' ) ) {
                console.log( data );
            }
        });
    });
    </script>
    <?php
}
add_action( 'admin_print_footer_scripts', 'wpse162220_print_javascript', 999 );

You should see it print something like

 Object {wpse162220: "foobar"} 

to the console every ~4 seconds.

|improve this answer|||||
  • Thank you for this clarification. It's a little disappointing that this is not anything close to real long-polling. I was expecting that in every beat I will be able to bind my response to some event (like for example new post inserted). As you explained, I rather have to manually query data each time making this impossible to handle bigger number of simultaneous connections. Thanks anyway. – user3562259 Sep 24 '14 at 12:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.