2015-04-13 12 views
7

Desidero richiamare in modo asincrono un comando da un controller in Symfony2.Chiamare in modo asincrono un comando in Symfony2

Finora ho trovato la seguente soluzione:

$cmd = $this->get('kernel')->getRootDir().'/console '.(new MLCJobWorkerCommand)->getName().' '.$job->getId().' 2>&1 > /dev/null'; 
$process = new Process($cmd); 
$process->start(); 

C'è un modo migliore per ottenere questo risultato?

Edit:

ho bisogno del processo per l'esecuzione in background e il controller per tornare subito dopo è iniziato il primo. Ho provato:

$cmd = $this->get('kernel')->getRootDir().'/console ' 
    .(new MLCJobWorkerCommand)->getName() 
    .' '.$job->getId().' 2>&1 > /dev/null & echo \$!'; 
$process = new Process($cmd); 
$process->mustRun(); 
$params["processid"] = $process->getOutput(); 

ma il controller non restituisce una risposta fino al termine del processo.

+2

Il problema è che il nuovo processo si fermerà non appena il processo padre viene arrestato pure, che è una limitazione in PHP. Una soluzione migliore potrebbe essere l'uso di un sistema di accodamento come RabbitMQ. – Gerry

+0

Sembra magnifico, farò un tentativo. In passato ero solito avviare un processo in background in PHP nel modo indicato dalla mia modifica ma il Controller sembra bloccarsi qui. Questo è legato al tuo commento? – dmb

risposta

4

Sono d'accordo con Gerry che se si vuole essere "asincrono" allora non selezionato il miglior modo

posso suggerire un'alternativa di RabbitMQ: JMSJobBundle
http://jmsyst.com/bundles/JMSJobQueueBundle/master/installation

cui è possibile creare una coda di voi comandi della console qualcosa di simile:

class HomeController ... { 
    // inject service here 
    private $cronJobHelper; 
    // inject EM here 
    private $em; 

    public function indexAction() { 
     $job = $this->cronJobHelper->createConsoleJob('myapp:my-command-name', $event->getId(), 10); 
     $this->em->persist($job); 
     $this->em->persist($job); 
     $this->em->flush(); 
    } 
} 


use JMS\JobQueueBundle\Entity\Job; 

class CronJobHelper{ 

    public function createConsoleJob($consoleFunction, $params, $delayToRunInSeconds, $priority = Job::PRIORITY_DEFAULT, $queue = Job::DEFAULT_QUEUE){ 
     if(!is_array($params)){ 
      $params = [$params]; 
     } 

     $job = new Job($consoleFunction, $params, 1, $queue, $priority); 
     $date = $job->getExecuteAfter(); 
     $date = new \DateTime('now'); 
     $date->setTimezone(new \DateTimeZone('UTC')); //just in case 
     $date->add(new \DateInterval('PT'.$delayToRunInSeconds.'S')); 
     $job->setExecuteAfter($date); 

     return $job; 
    } 
} 
+0

Grazie, JMSJobBundle sembra essere esattamente ciò di cui ho bisogno. – dmb

0

Checkout AsyncServiceCallBundle, che permette di chiamare completamente i metodi del servizio in modo asincrono USI ng this approccio. Il processo responsabile dell'attuale gestione delle richieste non attende la fine del figlio.

Tutto ciò che serve è quello di chiamare in questo modo:

$pid = $this->get('krlove.async')->call('service_id', 'method', [$argument1, $argument2]); 
Problemi correlati