Running a background task using Symfony Process without having to wait for the process to finish

laravel process
laravel process command
symfony processbuilder
symfony async process
symfony command
php background process
symfony process environment variable
symfony process fork

After a user submits a form, I want to render a view file, and right after that I want to initiate a background task to process five MS Excel files (each may have up to 2000 rows) , but in way so that the user don't have to wait for the process to finish in order to view the page. After the task is finished I will inform the user through an email.

I am using Symfony Framework 3. I have included my code below. Its not doing what I am trying to achieve. After submitting the form the page loads only when the entire background task is complete.

I am not sure but after googling a lot, I think The kernel.terminate Event could be useful here. But I can't seem to understand how to work with it.

Could you please tell me how to solve this problem ?

Here's my code:

I have created a Console Command:

class GreetCommand extends ContainerAwareCommand {

  protected function configure()
  {
    $this->setName('hello:world');
  }

  protected function execute(InputInterface $input, OutputInterface $output)
  {
   // My code to execute
  }

}

And in my controller I have

$process = new Process('ls -lsa');
$process->disableOutput();
$that = $this;

$process->start(function ($type, $buffer) use ($that) {
        $command = new GreetCommand();
        $command->setContainer($this->container);
        $input = new ArrayInput(array());
        $output = new NullOutput;
        $resultCode = $command->run($input, $output);

 });

 return $this->render('success.html.php',  array('msg' => 'Registraion Successful'));
Update

I have solved the problem using the connection-handling feature of PHP.

Thanks to this post

Running Processes Asynchronously

You can also start the subprocess and then let it run asynchronously, retrieving output and the status in your main process whenever you need it. Use the start() method to start an asynchronous process

documentation

so, to start your command asynchronously you should create new process with command and start it

$process = new Process('php bin/console hello:word');
$process->start();

Consider to change this to full paths like \usr\bin\php \var\www\html\bin\console hello:word

Also there is good bundle cocur/background-process you may use it, or at least read the docs to find out how it works.

The Process Component (Symfony Docs), Stopping a Process; Executing PHP Code in Isolation; Using a Prepared a command in a sub-process, taking care of the differences between operating system and is not found in the list of environment variables attached to the command. You can also wait for a process to end if you started it asynchronously and are� It means that your task will be stopped right away. Running an asynchronous process is not the same as running a process that survives its parent process. If you want your process to survive the request/response cycle, you can take advantage of the kernel.terminate event, and run your command synchronously inside this event.

For using in controller:

use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;

$myVar = new MyObject();
$this->get('event_dispatcher')->addListener(KernelEvents::TERMINATE, function(PostResponseEvent $event) use($myVar) {
    //You logic here
    $request = $event->getRequest();
    $test = $myVar->getMyStuff();
});

But it is not a good practice, please read about normal registering event listeners

kernel.terminate event will be dispatched after sending the response to user.

Symfony Process Start A Background Process From Browser � Issue , Running a background task using Symfony Process without having to wait for the process to finish - php. @subins2000 as you said, you want "to run a process without the server having to wait to finish it before sending the response back to the user". That's exactly why we introduced the kernel.terminate event. You can read more about this here and here. I'm closing this issue because it looks like the feature request is already implemented by Symfony.

I am a bit late to the game, but I just found a solution for this problem using the fromShellCommandLine() method:

use Symfony\Component\Process\Process;

Process::fromShellCommandline('/usr/bin/php /var/www/bin/console hello:world')->start();

This way it is possible to start a new process/run a command asynchronously.

Please add a basic example of running a heavy-duty background , I need to execute a PHP file in background to download a file. you want "to run a process without the server having to wait to finish it before sending the to the client while the server's PHP process still performs some tasks. You can send a running process to background as well. What you have to do here is to use Ctrl+Z to suspend the running process and then use ‘bg‘ (short for background) to send the process in background. The suspended process will now run in background. running_command ^z bg. Let’s take the same example as before.

I guess what you want is to store the necessary data in a database and then have a cronjob/queue execute the actual command, instead of trying to execute it directly from your controller.

Add something like the following to your /etc/crontab to let it run your command every 5 minutes

*/5 * * * * root /usr/bin/php /path/to/bin/console hello:world

Then, let your command query the database for the stored data and have it process the excel files

How to Run Symfony Processes Asynchronously, Running an asynchronous process is not the same as running a process that - a-background-task-using-symfony-process-without-having-to-wait-for-the-p Be aware that kernel.terminate is called only if you use PHP-FPM. 14 Running a background task using Symfony Process without having to wait for the process to finish Jun 9 '16 13 Ajax response inside a div May 13 '12 13 Validating array inputs using jquery validation plugin Jun 1 '12

There is a bundle called AsyncServiceCallBundle which allows you to call your service's methods in background.

You can refer this answer for more details about how it is done internally. Everything you need is to invoke your service's method as follows:

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

Using Background Processing to Speed Up Page Load Times , Running a background task using Symfony Process without having to wait for the process to finish. 发表于2019-9-24 | | 暂无分类. After a user submits a form,� All the libraries here are schedulers for running recurring/periodic background tasks within ASP.NET. There's another category of "background tasks" in ASP.NET that I find people ask for a lot: the ability to "return early" from a request and then have the server do a bit more work.

Managing Background Processes within Symfony, Each process waits on each other - one is finished, then next starts. How to Go Async in PHP? Luckily, Symfony Process already allows standalone process without waiting on each other. Don't forget to check that your CPU is not burned by running many processes at once by limiting concurrency. In� The main application function starts the background calculation in a separate thread, then waits for the thread to complete its work and finally prints the result global variable. The version of this function that you see above does not have the waiting part implemented, you can see a TODO comment in the place where the wait needs to take place.

Spawning a separate process for a long task : PHP, You can create multiple worker instances (processes) to speed up processing, We're using the Beanstalkd job queue to store jobs, the Symfony Console Once installed, Supervisor will be running in the background as a daemon. In our case, we'd have to wait for all our workers to finish their tasks or� The Wait-Process cmdlet waits for one or more running processes to be stopped before accepting input. In the PowerShell console, this cmdlet suppresses the command prompt until the processes are stopped. You can specify a process by process name or process ID (PID), or pipe a process object to Wait-Process. Wait-Process works only on processes running on the local computer.

For time-dependent tasks (i.e. run a specific command every 30 minutes) This ensures that our background processes remain in-sync with the current would not suffice, and having multiple workers running would be a requirement too. From a cold-start you would have to wait for multiple invocation� Wait() for the task, or: The GC calls the finalizer on the Task. You can handle yourself 1. and 2. shortly after you call the method, or you can attach a continuation with myTask.OnComplete(myErrorHandler, TaskContinuationOptions.OnlyOnFaulted) to be run when the original task throws an exception. 3. will crash your process; don't do that.

Comments
  • It would be useful to update your post with a little bit of info regarding the implementation of connection-handling feature!
  • @mpilliador - you could simply create an event listener on kernel.terminate or run process asynchronously (see Denis Alimov answer below).
  • Thank you very much for your answer. I already tried the above code, but its still waiting for the process to finish and then rendering the page. Do you think its because I am on windows, may be if I move to Linux it would work?
  • @black_belt yep, this maybe the cause of this.
  • @black_belt, no. it is not because you are on windows. Your main process is the application that launches the process. The output stream of sub-process is attached to the main process and it will block application process from termination until child press finishes.
  • This answer does not sound right. It says in the doc: "If a Response is sent before a child process had a chance to complete, the server process will be killed (depending on your OS)." That's the opposite of what the question asked for.
  • @Alexander Rechsteiner you are looking at Symfony 4 documentation. 2 years ago we were talking about Symfony 2 I guess.
  • Please note, this is only available in 4.3+.