8

I am new on Symfony2 and I got blocked when trying to run an asynchronous command like this:

class MyCommand extends ContainerAwareCommand{

protected function configure()
{
    $this
        ->setName('my:command')
        ->setDescription('My command')
        ->addArgument(
            'country',
            InputArgument::REQUIRED,
            'Which country?'
        )
    ;
}

protected function execute(InputInterface $input, OutputInterface $output)
{

    $country = $input->getArgument('country');


    // Obtain the doctrine manager
    $dm = $this->getContainer()->get('doctrine_mongodb.odm.document_manager');

   $users = $dm->getRepository('MyBundle:User')
        ->findBy( array('country'=>$country));
}}

That works perfectly when I call it from my command line:

php app/console my:command uk

But it doesn't work when I call it trowh a Symfony2 Process:

 $process = new Process("php ../app/console my:command $country");
 $process->start();

I get a database error: "[MongoWriteConcernException] 127.0.0.1:27017: not master"

I think that means that the process is not getting my database configuration...

I just want to run an asynchronous process, is there other way to do it?

Maybe a way to call the Application Command that do not require the answer to keep going ?

Maybe I need to use injection?

PS: My current command is just a test, at the end it should be an 'expensive' operation...

blueocean
  • 171
  • 2
  • 7
  • 2
    Well, I find the solution by myself. Actually it was a silly problem... I've added the environment parameter (**--env=**) to the process and everything worked like a charm: `$process = new Process("php ../app/console my:command $country --env=test");` – blueocean May 27 '14 at 16:28

3 Answers3

6

Well, I found out what happened...

I use multiple environments: DEV, TEST and PROD.

And I also use differents servers.

So the DEV environment is my own machine with a simple mongodb configuration. But the TEST environment is on other server with a replica set configuration...

Now the error get full sense: "[MongoWriteConcernException] 127.0.0.1:27017: not master"

To solve it, I've just added the environment parameter (--env=) to the process and everything worked like a charm:

$process = new Process("php ../app/console my:command $country --env=test");

Actually, to get the correct environment I use this:

$this->get('kernel')->getEnvironment();

Which let's my code as follows:

$process = new Process("php ../app/console my:command $country --env=".$this->get('kernel')->getEnvironment());

Maybe is not a beautifull way to do it, but it works for me :)

blueocean
  • 171
  • 2
  • 7
  • you should also use the `%kernel.root_dir%` container parameter to create the path to `app/console` – NDM May 13 '15 at 15:31
1

Disclamer: This might be a bit overkill for what you're trying to do :)

I would choose an opposite way to do it: pthreads

First, quick examination of StackOverflow showed me a really nice example of using pthreads: Multi-threading is possible in php

Then, knowing that you could invoke your command from another command:

http://www.craftitonline.com/2011/06/calling-commands-within-commands-in-symfony2/

... lets you piece all the parts. It's a bit complicated but it does the job.

Community
  • 1
  • 1
Jovan Perovic
  • 19,846
  • 5
  • 44
  • 85
  • Thank you for your answer @jperovic. Yes, like you said, I was looking for something easier ;) – blueocean May 27 '14 at 16:30
  • Ah, I've just read your comment to original question. Glad you resolved the problem. If it's not a problem please add an answer yourself - I'm sure someone will find it useful, sooner or later... ;) – Jovan Perovic May 27 '14 at 16:49
0

In case you want to execute your code completely async in Symfony2/3 there is AsyncServiceCallBundle for that.

You should just call it like this:

$this->get('krlove.async')->call('your_service_id', 'method_name', [$arg1, $arg2]);

Internally it uses this approach to run your code in background.

Andrii Mishchenko
  • 2,626
  • 21
  • 19