3

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.

George Irimiciuc
  • 4,573
  • 8
  • 44
  • 88

4 Answers4

4

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:

Using in symfony

RabbitMQBundle

Let RabbitMQ Do The Work In Your Symfony2 Application

Community
  • 1
  • 1
Tomasz Madeyski
  • 10,742
  • 3
  • 50
  • 62
2

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

Listener example

The kernel.terminate Event documentation

Anna Adamchuk
  • 718
  • 4
  • 16
  • The problem with kernel.terminate is that it will listen at every request and it doesn't make sense when I need it only in one place. – George Irimiciuc Feb 23 '16 at 08:33
  • Another problem is adding too many events for request, response, terminate makes the application slow, I believe. I could be wrong, but it still doesn't make sense to ask for this at every request. – George Irimiciuc Mar 09 '16 at 07:57
1

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

Community
  • 1
  • 1
Evgeniy Kuzmin
  • 2,384
  • 1
  • 19
  • 24
0

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

    }


}
George Irimiciuc
  • 4,573
  • 8
  • 44
  • 88
  • it is a bit hackish. It probably will work (I'm not sure about "\" directory separator in linux) but it's not clean code - let's imagine that name of command will change to `cache:clear-now` or `console` will change to `ezpublish` (in fact it is called this way in `ezpublish` cms) and it won't work anymore – Tomasz Madeyski Feb 23 '16 at 09:30
  • Then those can be added as parameters above. Even so, it's most likely they won't change (while we should not depend on this fact, there are quite a number of projects that have the command hard-coded somewhere in deployment scripts) and it's supposed to be working only for Symfony. – George Irimiciuc Feb 23 '16 at 10:19
  • I've changed it so more commands can be added to it. So far it's working splendidly. – George Irimiciuc Mar 09 '16 at 07:49