[wp-trac] [WordPress Trac] #46465: Implement logic that performs PHP code after connection with client is closed

WordPress Trac noreply at wordpress.org
Mon Mar 11 16:20:07 UTC 2019


#46465: Implement logic that performs PHP code after connection with client is
closed
-------------------------+-----------------------------
 Reporter:  umchal       |      Owner:  (none)
     Type:  enhancement  |     Status:  new
 Priority:  normal       |  Milestone:  Awaiting Review
Component:  General      |    Version:
 Severity:  normal       |   Keywords:
  Focuses:               |
-------------------------+-----------------------------
 Hi there,

 It would be great if this can be implemented in the core.

 When I write plugins, it is almost unavoidable to perform extra database
 queries like accessing a custom database table, updating rows, and
 scheduling WP Cron actions etc. The problem is that it affects the page
 load time.

 I've been wondering how this can be avoided and how the impact on the
 performance can be made minimum from the user experience perspective.

 And I came up with a little technique using `header('Content-Length: n')`
 and `header('Connection: close' )`. Here is a working example plugin.

 {{{#!php
 <?php
 /**
  * Plugin Name: Test - HTTP Connection Close
  */

 class HTTPConnectionClose {

     public function __construct() {

         add_action( 'init', array( $this, 'startCapturing' ) );
         add_action( 'shutdown', array( $this, 'endCapturing' ),
 PHP_INT_MIN );

     }

     public function startCapturing() {
          ob_start();
     }

     /**
      * @remark      Should be called before `wp_ob_end_flush_all()`.
      */
     public function endCapturing() {

         $_iOutputBufferLength = ( integer ) ob_get_length();
         if ( ! headers_sent() ) {
             @header('Content-Length: ' . $_iOutputBufferLength ) ;
             @header('Connection: close' );
         }
         if ( $_iOutputBufferLength ) {
             ob_end_flush();
         }

     }

 }
 new HTTPConnectionClose;
 }}}

 Here are some examples that illustrate the benefits of this. You can add
 this code at the bottom of the above example plugin.

 {{{#!php
 class Test_HTTPConnectionClose {

     public function __construct() {

         add_action( 'shutdown', array( $this, 'testHeavyTask' ),
 PHP_INT_MAX );
         add_action( 'plugins_loaded', array( $this, 'testWPCronCheck' ) );
         add_action( 'shutdown', array( $this, 'testWPCronSchedule' ) );
         add_action( 'test_custom_action', array( $this,
 'testCustomCronTask' ) );

     }

     public function testCustomCronTask() {
         error_log( __METHOD__  . ': doing custom cron task.' );
     }

     /**
      * This causes a couple of database queries. But with the above
 technique, this will not be seen during the page load.
      */
     public function testWPCronSchedule() {
         $_aArguments  = array();
         $_sActionName = 'test_custom_action';
         if ( wp_next_scheduled( $_sActionName, $_aArguments ) ) {
             return;
         }
         wp_schedule_single_event( time() + 5, $_sActionName, $_aArguments
 );
     }

     /**
      * Checks registered WP Cron actions in the `shutdown` instead of
 `init` action
      * to save a little load time in every single page load.
      */
     public function testWPCronCheck() {
         remove_action( 'init', 'wp_cron' );
         if ( ! defined( 'DOING_CRON' ) ) {
                 add_action( 'shutdown', 'wp_cron' );
         }
     }

     /**
      * Simulates a heavy task which consumes 10 seconds. But with the
 above technique, the visitor do not feel any delay caused by this.
      */
     public function testHeavyTask() {
         sleep( 10 ); // sleep 10 seconds
         error_log( 'done a heavy task which takes 10 seconds.' );
     }

 }
 new Test_HTTPConnectionClose;
 }}}

 As you can see with the above `testHeavyTask()` method, any heavy sub-
 routines can be done in the `shutdown` action. Say, your plugin generates
 outputs and has a caching mechanism that schedules a task and calls `wp-
 cron.php` when the output is expired. With this, even scheduling a WP Cron
 task will be no longer needed. The plugin can update the cache in the
 `shutdown` action within the page load. This saves extra page load and
 also helps avoid PHP timeout issues in `wp-cron.php` due to too many
 registered WP Cron actions. Needless to say, this helps for sites
 disabling WP Cron.


 It's very short and should be technically feasible to implement. Not sure
 any side effects with this yet but maybe you guys can tell.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/46465>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list