Changeset 100598 in spip-zone for _plugins_


Ignore:
Timestamp:
Nov 21, 2016, 1:01:12 PM (3 years ago)
Author:
marcimat@…
Message:

Faire fonctionner le mode streaming avec certaines configurations (ici Mamp pro 4 / apache 2.4 / php 7), qui déséspérément
retournait les logs en 1 seul morceau… Je n'ai pas trouvé comment désactiver ce buffer, qui semble provenir d'apache ou d'un mod_xxx
d'apache. Pour que les morceaux partent, il faut un message long, et séparé de quelques ms du précédent.

Location:
_plugins_/migrateur/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/migrateur/trunk/CHANGELOG.md

    r90818 r100598  
    11CHANGELOG
    22=========
     3
     4Version 3.0.8
     5-------------
     6
     7Le streaming des logs avec MAMP Pro / Apache 2.4 / PHP 7 ne fonctionnait pas.
     8On tente de passer outre les buffers.
    39
    410Version 3.0.5
  • _plugins_/migrateur/trunk/action/migrateur.php

    r88473 r100598  
    77 * Lance une action de migration
    88 *
     9 * Si streaming des logs demandé, prépare le serveur pour.
     10 *
    911 * Charge la fonction migrateur_$arg() dans migrateur/$arg.php
    1012**/
     
    2224        $stream = (bool) _request('stream');
    2325        if ($stream) {
    24                 // forcer les logs à faire des echos
    25                 migrateur_log("", "", true);
    26                 // forcer l'absence de redirection ajax
    27                 $GLOBALS['redirect'] = "";
    28 
    29                 header('Content-type: text/html; charset=utf-8');
    30                 #header('Content-type: application/octet-stream;');
    31 
    32                 // Turn off output buffering
    33                 ini_set('output_buffering', 'off');
    34                 // Turn off PHP output compression
    35                 ini_set('zlib.output_compression', false);
    36                 // Implicitly flush the buffer(s)
    37                 ini_set('implicit_flush', true);
    38                 ob_implicit_flush(true);
    39                 // Clear, and turn off output buffering
    40                 while (ob_get_level() > 0) {
    41                         // Get the curent level
    42                         $level = ob_get_level();
    43                         // End the buffering
    44                         ob_end_clean();
    45                         // If the current level has not changed, abort
    46                         if (ob_get_level() == $level) break;
    47                 }
    48 
    49                 // Disable apache output buffering/compression
    50                 if (function_exists('apache_setenv')) {
    51                         apache_setenv('no-gzip', '1');
    52                         apache_setenv('dont-vary', '1');
    53                 }
     26                migrateur_preparer_streaming();
    5427        }
    5528
     
    10275
    10376
     77/**
     78 * Prépare le serveur pour envoyer des informations en streaming
     79 *
     80 * Tente de squizer les buffers, compressions, à différents endroits (php, apache, nginx…)
     81 *
     82 * @link http://stackoverflow.com/questions/7740646/jquery-ajax-read-the-stream-incrementally
     83 * @link http://www.jeffgeerling.com/blog/2016/streaming-php-disabling-output-buffering-php-apache-nginx-and-varnish
     84 * @link https://phpfashion.com/everything-about-output-buffering-in-php
     85**/
     86function migrateur_preparer_streaming() {
     87        // forcer les logs à faire des echos
     88        migrateur_log("", "", true);
     89
     90        // forcer l'absence de redirection ajax
     91        $GLOBALS['redirect'] = "";
     92
     93        header('Content-type: text/html; charset=utf-8');
     94        #header('Content-type: application/octet-stream;');
     95
     96        // Explicitly disable caching so Varnish and other upstreams won't cache.
     97        header("Cache-Control: no-cache, must-revalidate");
     98
     99        // Setting this header instructs Nginx to disable fastcgi_buffering and disable gzip for this request.
     100        header('X-Accel-Buffering: no');
     101
     102        // Turn off output buffering
     103        ini_set('output_buffering', 'Off');
     104
     105        // Turn off PHP output compression
     106        ini_set('zlib.output_compression', false);
     107
     108        // Implicitly flush the buffer(s)
     109        ini_set('implicit_flush', true);
     110        ob_implicit_flush(true);
     111
     112        // Clear, and turn off output buffering
     113        while (ob_get_level() > 0) {
     114                // Get the curent level
     115                $level = ob_get_level();
     116                // End the buffering
     117                ob_end_clean();
     118                // If the current level has not changed, abort
     119                if (ob_get_level() == $level) {
     120                        break;
     121                }
     122        }
     123
     124        // Disable apache output buffering/compression
     125        if (function_exists('apache_setenv')) {
     126                apache_setenv('no-gzip', '1');
     127                apache_setenv('dont-vary', '1');
     128        }
     129}
  • _plugins_/migrateur/trunk/inc/migrateur.php

    r88450 r100598  
    7070        static $stream = false;
    7171
     72        /* Forcer un echo sur les logs */
    7273        if (!is_null($set_stream)) {
    7374                $stream = (bool)$set_stream;
     
    7576        }
    7677
     78        /* créer le répertoire de log */
    7779        $dir = _DIR_TMP . 'migrateur';
    7880        if (!$done) {
     
    8284
    8385        if ($type) {
    84                 $message = '[' . $type . '] ' . $message;
     86                $msg = '[' . $type . '] ' . $msg;
    8587        }
    8688
    87         file_put_contents($dir . "/migrateur.log", date("Y:m:d H:i:s") . " | " . $msg . "\n", FILE_APPEND);
    88         file_put_contents($dir . "/etape.log", $msg . "\n", FILE_APPEND);
     89        file_put_contents($dir . "/migrateur.log", date("Y:m:d H:i:s") . " | " . $msg . PHP_EOL, FILE_APPEND);
     90        file_put_contents($dir . "/etape.log", $msg . PHP_EOL, FILE_APPEND);
    8991        spip_log($msg, 'migrateur');
    9092
    9193        if ($stream) {
    92                 echo $msg . "\n";
    93                 flush();
     94                migrateur_stream_log($msg);
    9495        }
     96}
     97
     98/**
     99 * Envoie un log (json) au navigateur
     100 *
     101 * Certaines configurations sont ennuyantes, pour passer outre la mise en buffer,
     102 * entre php, mod_xxx d'apache, apache, le navigateur.
     103 *
     104 * La fonction `migrateur_preparer_streaming()` fait tout son possible pour
     105 * les désactiver, mais cela ne suffit pas toujours.
     106 *
     107 * On force donc l'envoi d'un paquet assez gros (8ko) pour qu'il soit envoyé
     108 * à chaque fois au navigateur. Mais pas trop rapidement entre chaque
     109 * message, sinon, là encore, les messages peuvent se cumuler avant d'arriver
     110 * au navigateur (ce qui fait que le json n'est plus valide)…
     111 *
     112 * @param string $msg
     113 *    Le message à envoyer
     114**/
     115function migrateur_stream_log($msg) {
     116        /**
     117         * Si stream, forcer gros message, pour passer outre différents buffers…
     118         * Tristement…
     119         */
     120        static $buffer_size = 8 * 1024;
     121
     122        /**
     123         * Si stream, il faut un délai minimal entre 2 envois :/
     124         * Tristement…
     125         */
     126        static $delai_minimal_ms = 20; // 16 semble passer… soyons prudents
     127
     128        /**
     129         * Pour calculer le temps écoulé depuis le dernier envoi d'un log
     130         */
     131        static $chronometre = false;
     132
     133        if ($chronometre) {
     134                $last = intval(spip_timer('stream_log', true));
     135        } else {
     136                $last = 0;
     137        }
     138
     139        $message = json_encode(array('log' => $msg . PHP_EOL));
     140        echo str_pad($message, $buffer_size) . PHP_EOL;
     141        flush();
     142
     143        if ($last < $delai_minimal_ms) {
     144                usleep(($delai_minimal_ms-$last) * 1000);
     145        }
     146
     147        spip_timer('stream_log');
     148        $chronometre = true;
    95149}
    96150
  • _plugins_/migrateur/trunk/paquet.xml

    r90831 r100598  
    22        prefix="migrateur"
    33        categorie="outil"
    4         version="3.0.7"
     4        version="3.0.8"
    55        etat="dev"
    66        compatibilite="[2.1.0;3.1.*]"
  • _plugins_/migrateur/trunk/prive/squelettes/inclure/migrateur-destination.html

    r90816 r100598  
    144144                                                        last_response_len = response.length;
    145145                                                }
    146 
    147                                                 $log.append(this_response);
     146                                                var message = $.trim(this_response);
     147                                                if (message.length) {
     148                                                        message = $.parseJSON(message);
     149                                                        $log.append(message.log);
     150                                                }
    148151                                                if ($log.length) {
    149152                                                        $log.scrollTop($log.eq(0).scrollHeight - $log.height());
Note: See TracChangeset for help on using the changeset viewer.