Prechádzať zdrojové kódy

added a cache warmer sub-framework

Cache warmer will come in the next commits.

To warm up the cache on a production server, you can use
the cache:warmup command:

./app/console_prod cache:warmup
Fabien Potencier 14 rokov pred
rodič
commit
d0b4bfc8f6

+ 52 - 0
src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php

@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Command;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Warmup the cache.
+ *
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ */
+class CacheWarmupCommand extends Command
+{
+    /**
+     * @see Command
+     */
+    protected function configure()
+    {
+        $this
+            ->setName('cache:warmup')
+            ->setDescription('Warms up an empty cache')
+            ->setHelp(<<<EOF
+The <info>cache:warmup</info> command warms up the cache.
+
+Before running this command, the cache must be empty.
+EOF
+            )
+        ;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $output->writeln('Warming up the cache');
+
+        $warmer = $this->container->get('cache_warmer');
+        $warmer->enableOptionalWarmers();
+        $warmer->warmUp($this->container->getParameter('kernel.cache_dir'));
+    }
+}

+ 45 - 0
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheWarmerPass.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Reference;
+
+/*
+ * This file is part of the Symfony framework.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * Registers the cache warmers.
+ *
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ */
+class AddCacheWarmerPass implements CompilerPassInterface
+{
+    /**
+     * {@inheritDoc}
+     */
+    public function process(ContainerBuilder $container)
+    {
+        if (!$container->hasDefinition('cache_warmer')) {
+            return;
+        }
+
+        $warmers = array();
+        foreach ($container->findTaggedServiceIds('kernel.cache_warmer') as $id => $attributes) {
+            $warmers[] = new Reference($id);
+        }
+
+        $container->getDefinition('cache_warmer')->setArgument(0, $warmers);
+
+        if ('full' === $container->getParameter('kernel.cache_warmup')) {
+            $container->getDefinition('cache_warmer')->addMethodCall('enableOptionalWarmers', array());
+        }
+    }
+}

+ 7 - 1
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

@@ -157,6 +157,13 @@ class FrameworkExtension extends Extension
             $this->registerEsiConfiguration($config, $container);
         }
 
+        if (isset($config['cache-warmer'])) {
+            $config['cache_warmer'] = $config['cache-warmer'];
+        }
+
+        $warmer = isset($config['cache_warmer']) ? $config['cache_warmer'] : !$container->getParameter('kernel.debug');
+        $container->setParameter('kernel.cache_warmup', $warmer);
+
         $this->addClassesToCompile(array(
             'Symfony\\Component\\HttpFoundation\\ParameterBag',
             'Symfony\\Component\\HttpFoundation\\HeaderBag',
@@ -276,7 +283,6 @@ class FrameworkExtension extends Extension
 
         // compilation
         $this->addClassesToCompile(array(
-            'Symfony\\Component\\Templating\\DelegatingEngine',
             'Symfony\\Bundle\\FrameworkBundle\\Templating\\EngineInterface',
             'Symfony\\Component\\Templating\\EngineInterface',
         ));

+ 2 - 0
src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

@@ -21,6 +21,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RoutingResolverP
 use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass;
 use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddClassesToCachePass;
 use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\Compiler\PassConfig;
 use Symfony\Component\HttpFoundation\File\File;
@@ -82,6 +83,7 @@ class FrameworkBundle extends Bundle
         $container->addCompilerPass(new AddFieldFactoryGuessersPass());
         $container->addCompilerPass(new AddClassesToCachePass());
         $container->addCompilerPass(new TranslatorPass());
+        $container->addCompilerPass(new AddCacheWarmerPass());
     }
 
     /**

+ 9 - 0
src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

@@ -23,8 +23,17 @@
         <xsd:attribute name="ide" type="xsd:string" />
         <xsd:attribute name="charset" type="xsd:string" />
         <xsd:attribute name="error-handler" type="xsd:string" />
+        <xsd:attribute name="cache-warmer" type="cache_warmer" />
     </xsd:complexType>
 
+    <xsd:simpleType name="cache_warmer">
+        <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="false" />
+            <xsd:enumeration value="true" />
+            <xsd:enumeration value="full" />
+        </xsd:restriction>
+    </xsd:simpleType>
+
     <xsd:complexType name="profiler">
         <xsd:all>
             <xsd:element name="matcher" type="profiler_matcher" minOccurs="0" maxOccurs="1" />

+ 5 - 0
src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml

@@ -11,6 +11,7 @@
         <parameter key="error_handler.class">Symfony\Component\HttpKernel\Debug\ErrorHandler</parameter>
         <parameter key="error_handler.level">null</parameter>
         <parameter key="filesystem.class">Symfony\Bundle\FrameworkBundle\Util\Filesystem</parameter>
+        <parameter key="cache_warmer.class">Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate</parameter>
     </parameters>
 
     <services>
@@ -28,6 +29,10 @@
             <call method="setEventDispatcher"><argument type="service" id="event_dispatcher" /></call>
         </service>
 
+        <service id="cache_warmer" class="%cache_warmer.class%">
+            <argument type="collection" />
+        </service>
+
         <!--
             If you want to change the Request class, modify the code in
             your front controller (app.php) so that it passes an instance of

+ 31 - 0
src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php

@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpKernel\CacheWarmer;
+
+/**
+ *
+ * @author Fabien Potencier <fabien.potencier@symfony-project.org>
+ */
+abstract class CacheWarmer implements CacheWarmerInterface
+{
+    protected function writeCacheFile($file, $content)
+    {
+        $tmpFile = tempnam(dirname($file), basename($file));
+        if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
+            chmod($file, 0644);
+
+            return;
+        }
+
+        throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
+    }
+}

+ 72 - 0
src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php

@@ -0,0 +1,72 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpKernel\CacheWarmer;
+
+/**
+ *
+ * @author Fabien Potencier <fabien.potencier@symfony-project.org>
+ */
+class CacheWarmerAggregate implements CacheWarmerInterface
+{
+    protected $warmers;
+    protected $optionalsEnabled;
+
+    public function __construct(array $warmers = array())
+    {
+        $this->setWarmers($warmers);
+        $this->optionalsEnabled = false;
+    }
+
+    public function enableOptionalWarmers()
+    {
+        $this->optionalsEnabled = true;
+    }
+
+    /**
+     * Warms up the cache.
+     *
+     * @param string $cacheDir The cache directory
+     */
+    public function warmUp($cacheDir)
+    {
+        foreach ($this->warmers as $warmer) {
+            if (!$this->optionalsEnabled && $warmer->isOptional()) {
+                continue;
+            }
+
+            $warmer->warmUp($cacheDir);
+        }
+    }
+
+    /**
+     * Checks whether this warmer is optional or not.
+     *
+     * @return Boolean always true
+     */
+    public function isOptional()
+    {
+        return false;
+    }
+
+    public function setWarmers(array $warmers)
+    {
+        $this->warmers = array();
+        foreach ($warmers as $warmer) {
+            $this->add($warmer);
+        }
+    }
+
+    public function add(CacheWarmerInterface $warmer)
+    {
+        $this->warmers[] = $warmer;
+    }
+}

+ 38 - 0
src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerInterface.php

@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpKernel\CacheWarmer;
+
+/**
+ *
+ * @author Fabien Potencier <fabien.potencier@symfony-project.org>
+ */
+interface CacheWarmerInterface
+{
+    /**
+     * Warms up the cache.
+     *
+     * @param string $cacheDir The cache directory
+     */
+    function warmUp($cacheDir);
+
+    /**
+     * Checks whether this warmer is optional or not.
+     *
+     * Optional warmers can be ignored on certain conditions.
+     *
+     * A warmer should return true if the cache can be
+     * generated incrementally and on-demand.
+     *
+     * @return Boolean true if the warmer is optional, false otherwise
+     */
+    function isOptional();
+}

+ 7 - 0
src/Symfony/Component/HttpKernel/Kernel.php

@@ -427,15 +427,22 @@ abstract class Kernel implements HttpKernelInterface, \Serializable
         $location = $this->getCacheDir().'/'.$class;
         $reload = $this->debug ? $this->needsReload($class, $location) : false;
 
+        $fresh = false;
         if ($reload || !file_exists($location.'.php')) {
             $container = $this->buildContainer();
             $this->dumpContainer($container, $class, $location.'.php');
+
+            $fresh = true;
         }
 
         require_once $location.'.php';
 
         $this->container = new $class();
         $this->container->set('kernel', $this);
+
+        if ($fresh && 'cli' !== php_sapi_name()) {
+            $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
+        }
     }
 
     public function getKernelParameters()