Reputation: 267
I want to asynchronously call a Command from within a Controller in Symfony2.
So far i found the following solution:
$cmd = $this->get('kernel')->getRootDir().'/console '.(new MLCJobWorkerCommand)->getName().' '.$job->getId().' 2>&1 > /dev/null';
$process = new Process($cmd);
$process->start();
Is there a better way to accomplish this?
Edit:
I need the Process to run in background and the Controller to return right after it started the former. I tried:
$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();
but the Controller doesn't return a Response until the Process has finished.
Upvotes: 8
Views: 5078
Reputation: 2694
Checkout AsyncServiceCallBundle, it allows you to call your service's methods completely asynchronously using this approach. The process responsible for current request handling doesn't wait for its child to be finished.
Everything you need is to call it like this:
$pid = $this->get('krlove.async')->call('service_id', 'method', [$argument1, $argument2]);
Upvotes: 0
Reputation: 2462
I agree with Gerry that if you want to be "asynchronously" then you selected not the best way
I can recommend an alternative of RabbitMQ: JMSJobBundle
http://jmsyst.com/bundles/JMSJobQueueBundle/master/installation
Where you can create a queue of you console commands something like:
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;
}
}
Upvotes: 5