Thread PHP dans Copix via HTTP

Dans le précédent post Thread PHP dans Copix, j’ai présenté la méthode thread via pcntl. Cette méthode fonctionne convenablement sur Unix et en mode client console. Sauf que voilà, en mode WEB on ne pourra pas l’utiliser. Je me suis penché sur le sujet, et je n’ai trouvé qu’une seule et unique solution. J’ai donc recréé ma classe CopixThread dans un module et je vais vous expliquer comment je m’en sors. Sachez avant tout que **ça fonctionne très bien** et surtout je n’ai **plus de restriction en terme de plateforme, cela fonctionne partout** :).

Puisque nous n’avons pas un processus réél de PHP, nous ne pouvons pas créer un thread ou un fork. Par contre, quelque chose en amont utilise parfaitement les thread et on va s’en servir. Vous le connaissez, il se nomme **Apache**

Et oui, Apache permet de répondre simultanément à plusieurs clients. Nous allons donc faire en sorte que notre manager de thread puisse envoyer les demandes à Copix via Apache. En ouvrant des sockets, nous serons en mode “non bloquant” ce qui signifie que nous allons attendre nos données indéfiniement et sans coincer les autres sockets (du moins avec un timeout).

Après coup, nous continuerons notre processus. L’intérêt est simple: créer une structure de données et la faire travailler en parallèle d’autres tâches. Je vais vous montrer un exemple de traitement qui devrait travailler plus de 9 secondes mais ne saura finalement réalisé qu’en 5 secondes.

D’abord, présentons la classe Thread comme je l’ai implémenté. abstract class Thread { public $response; public abstract function process(); }

\$response contiendra le retour de process qui sera la méthode appelé lors de l’instanciation du thread.

Maintenant, voyons 2 nouvelles classes. Ces classes: ` <?php //test.class.php class Test extends Thread { function process(){ //on imagine 4 secondes de calcul sleep(4); return “Test: ok j’ai terminé’“; }

}

?> <?php //test2.class.php class Test2 extends Thread { public $flag=1; function process(){ //je prend 5 secondes de calcul sleep(5); return “Test2: ok j’ai terminé aussi’“; }

} ?> `

Mes classes prennent donc 4 secondes pour l’une et 5 secondes pour l’autre, ce qui fait au total 9 secondes de traitement. C’est dommage, car en effet, si on faisait tourner nos deux classes en parallèle, le traitement total ne serait que 5 secondes, c’est à dire le temps le plus long possible pour une classe.

Et bien avec le manager que j’ai créé, on va avoir à peu près ce résultat.

Voici un actiongroup qui va faire office de test. ` <?php class ActionGroupTest extends CopixActionGroup { function processDefault (){
//création du manager de thread $manager = _ioClass(‘ThreadManager’);

   //j'ajoute 2 threads
   $manager->add("test");
   $manager->add('test2');

   //et j'appelle l'éxecution
   $manager->execute();

   //juste question de présenter les réponses
   $ppo = new CopixPPO();               
   $ppo->MAIN = nl2br(str_replace(" "," ",var_export($manager->reponses,true)));
   return _arPPO($ppo,"generictools|blank.tpl");        
}

} ?> `

Le résultat est:

array (
  0 => 
  Test::__set_state(array(
     'response' => 'Test: ok j'ai terminé',
     'session' => NULL,
  )),
  1 => 
  Test2::__set_state(array(
     'flag' => 1,
     'response' => 'Test2: ok j'ai terminé aussi',
     'session' => NULL,
  )),
)

On a, dans nos réponses, les objets en retour. Nous voyons bien que la classe Test2 a toujours sa propriété “flag”, donc vous pouvez stocker ce que vous voulez à l’intérieur de votre classe.

Ayant activé le plugin Copix qui me donne le temps total de génération, je vois apparaître le temps **5.345**

  • - 5 secondes !!** et oui, je vous avais prévenu.

Alors le souci pour le moment c’est que mes classes qui héritent de Thread **ne peuvent pas** utiliser les sessions… L’idée c’est que le client n’est plus le navigateur, mais Copix lui même, depuis le serveur. De ce fait, la session n’est pas la même. J’aimerai trouvé le moyen de forcer cela, mais pour le moment ce n’est pas la question. D’ailleurs vous pouvez pallier le soucis en stockant les session dans votre classe de thread.

Un dernier point, la méthode add prend le chemin typique de copix module|nom de classe. Pour mes tests, les classes étaient dans le module Thread je n’ai donc pas eut à forcer le nom du module.

Voilà, quand j’aurai nettoyé tout ça, je le présenterai dans le tronc de Copix. Je pense qu’il sera de base dans Copix 3.1.

comments powered by Disqus