Développer avec RBS Change : Lancement de processus en assynchrone

  • 82446.1

    16/01/2014 16:07


    dimitri s.
    Rang : Nouveau Membre
    Bonjour,

    Je dois lancer un traitement pouvant être potentiellement lourd dans RBS, lors de la création d'un utilisateur. Afin de ne pas rester bloqué sur la page ou récupérer une timeout exception, je voudrais lancer ce traitement dans un autre thread.
    A part avec une tâche, je ne vois pas trop somment gérer cela dans RBS.

    Pourriez-vous me dire si ma logique est correcte et si c'est le cas me dire comment provoquer l'exécution d'une tâche à partir d'un bloc?

    Merci d'avance.

    Dimitri.

    RBSChange 3.6.7
  • 82446.2 en réponse à 82446.1 écrit par dimitri s.

    17/01/2014 15:29


    Jean-Michel
    Titre : Community Manager
    Rang : Expert
    Bonjour Dimitri,

    La logique ne me semble pas poser de problème. Ce qu'il faut donc faire consiste à modifier ce qu'il se passe dans la méthode "postInsert()" du service du document user qui t'interresse (frontend, backend, user) afin de créer la tâche planifiée qu'il convient (de moins point de vue, mieux vaut passer par une injection du document concerné que par de l'AOP).

    La méthode "postInsert" du service ressemblera à quelque chose comme :
    protected function postInsert($document, $parentNodeId = null)
    {
    	parent::postInsert($document, $parentNodeId);
    	$taskLabel = "Grosse action userId ".$document->getId();
    	$tasks = task_PlannedtaskService::getInstance()->createQuery()
    		->add(Restrictions::eq('systemtaskclassname', 'monmodule_ClasseDeMaTache'))
    		->add(Restrictions::eq('label', $taskLabel))
    		->find();
    	if (f_util_ArrayUtils::isEmpty($tasks))
    	{
    		$task = task_PlannedtaskService::getInstance()->getNewDocumentInstance();
    		$task->setSystemtaskclassname('monmodule_ClasseDeMaTache');
    	}
    	else
    	{
    		$task = f_util_ArrayUtils::firstElement($tasks);
    	}
    	$task->setLabel($taskLabel);
    	$task->setMeta("userId", $document->getId());
    	$task->setUniqueExecutiondate(date_Calendar::getInstance()->add(date_Calendar::MINUTE, 1));
    	$task->save(ModuleService::getInstance()->getSystemFolderId('task', 'monmodule'));
    }


    Et le code de la classe de la tâche ("modules/monmodule/lib/tasks/ClasseDeMaTache.php") pourrait ressembler à :
    class monmodule_ClasseDeMaTache extends task_SimpleSystemTask
    {
    	/**
    	 * @see task_SimpleSystemTask::execute()
    	 */
    	protected function execute()
    	{
    		$userId = $this->plannedTask->getMeta("userId");
    
    		$index = 0;
    		$chunkSize = 50;
    		$runChunk = true;
    		while ($runChunk)
    		{
    			$output = $this->launchChunk($userId, $index, $chunkSize);
    			if (!is_numeric($output))
    			{
    				// Une erreur s'est produite, on réagit par un envoi de mail ou autre
    				// code pour gérer le cas d'erreur...
    				$runChunk = false;
    			}
    			if (intval($output) == $chunkSize)
    			{
    				$index += intval($output);
    			}
    			else
    			{
    				// La valeur de la sortie est plus petite que celle de la taille du chunk :
    				// Cela indique que l'exécution du chunk est terminée
    				// On réagit pas une notification ou autre
    				$index += intval($output);
    				$runChunk = false;
    				// Code à exécuter en cas de succès
    			}
    		}
    	}
    
    	private function launchChunk($userId, $index = 0, $chunkSize = 50)
    	{
    		$scriptPath = "modules/monmodule/lib/chunk/chunkUser.php";
    		$params = array($userId, $index, $chunkSize);
    		return f_util_System::execScript($scriptPath, $params);
    	}
    
    }


    Et le code de mon chunk ("modules/monmodule/lib/chunk/chunkUser.php") à quelque chose de ce type :
    <?php
    $params = $_POST['argv'];
    
    list($userId, $index, $chunkSize) = $params;
    
    try
    {
    	$user = DocumentHelper::getDocumentInstance($userId);
    	if ($user)
    	{
    		// Récupération du bon service de document pour mon $user
    		$userService = $user->getDocumentService();
    		// code à exécuter
    		// en cas d'erreur faire un echo d'un chaine
    
    		// Définition d'un flag de fin de chunk selon vos critères
    		$end = true;
    	}
    	else
    	{
    		$error = "Unable to find user with id ".$userId;
    		throw new Exception($error);
    	}
    
    	// Si plus besoin d'exécuter le chunk faire un echo de d'une
    	// valeur différente de chunkSize (peut être le nombre d'itération
    	// dans le traiement du chunk par exemple) sinon de faire un
    	// echo de $chunkSize
    	if ($end)
    	{
    		echo $chunkSize++;
    	}
    	else
    	{
    		echo $chunkSize;
    	}
    }
    catch (Exception $e)
    {
    	$msg = "EXCEPTION OCCURED : ".$e->getMessage();
    	echo $msg;
    	// Log
    	Framework::exception($e);
    }
    


    En espérant avoir répondu à tes questions.

    Pour une meilleure réponse, pensez à indiquer la version sur laquelle vous rencontrez des difficultés, ainsi que son type (CMS ou eCommerce core).
    Pour tout problème d'installation indiquez le nom de l'hébergeur et s'il s'agit d'un serveur mutualisé ou dédié.
  • 82446.3 en réponse à 82446.2 écrit par Jean-Michel

    20/01/2014 11:30


    dimitri s.
    Rang : Nouveau Membre
    Bonjour Jean-Michel,

    Je test cela et confirme la validité de la solution.

    Merci beaucoup.

    Dimitri.
 
Merci de prendre connaissance et de respecter les règles des forums.
 
1449 membres
Aucun membre connecté