简体   繁体   中英

Asynchronously calling a Command in Symfony2

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.

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;
    }
}

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]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM