Reputation: 4633
I want to clear the cache from the controller. I have defined the command as a service and call it.
clear_cache_command_service:
class: Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand
calls:
- [setContainer, ["@service_container"] ]
In my controller I have a form to choose a command, and when the cache-clearing command is chosen it runs:
$clearCacheCommand = $this->container->get('clear_cache_command_service');
$clearCacheCommand->run(new ArrayInput(array()), new ConsoleOutput());
This however runs for a while, since it also warms up the cache (I actually want it to also warm it up). It also times out so I need to set_time_limit
it, too.
Is there a way to return a response in the browser and let the command run and finish on the server? I don't want the client to keep waiting for it to finish.
Upvotes: 3
Views: 1496
Reputation: 4633
I found a way to do it. This will immediately return a response and have the command run in background. Not sure how much of a bad practice it is.
/**
* @Service("background_command_runner")
*/
class BackgroundCommandRunner
{
private $kernelDir;
/**
* @InjectParams({
* "kernelDir" = @Inject("%kernel.root_dir%")
* })
*/
public function __construct($kernelDir)
{
$this->kernelDir = $kernelDir;
}
public function run($cmd)
{
$path = $this->kernelDir . '\console ';
$fullCmd = "php " . $path . $cmd;
if (substr(php_uname(), 0, 7) == "Windows") {
pclose(popen("start /B " . $fullCmd, "r"));
} else {
exec($fullCmd . " >> logs/theme.log &");
}
}
public function clearCache($env = "dev", $warm = true)
{
$toWarm = $warm ? "" : " --no-warmup";
$cmd = "cache:clear " . "--env=" . $env . $toWarm;
$this->run($cmd);
}
}
Upvotes: 0
Reputation: 2462
As an alternative of RabbitMQ that was mentioned about already, you can take a look to JMSJobBundle http://jmsyst.com/bundles/JMSJobQueueBundle/master/installation
Some code example I gave at this my older answer to similar question: Asynchronously calling a Command in Symfony2
Upvotes: 1
Reputation: 720
For running command after response you have to use listener on kernel.terminate event. The purpose of this event is to perform tasks after the response was already served to the client.
// send the headers and echo the content
$response->send();
// triggers the kernel.terminate event
$kernel->terminate($request, $response);
The kernel.terminate Event documentation
Upvotes: 2
Reputation: 10890
Because of how php
works - synchronously - it is not possible to do in a "classic" way in which you need to wait until command completes to terminate and send the response. Solution here is to incorporate worker
pattern. You can find some useful info here. Basically you need to add "clear cache" task to queue and let other process handle this queue so in you case call clear cache
command.
A common solution used in symfony in such cases is using RabbitMQ, there's a lot of resources about it:
Let RabbitMQ Do The Work In Your Symfony2 Application
Upvotes: 4