Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache warmers #1258

Open
wants to merge 11 commits into
base: 2.x
Choose a base branch
from
90 changes: 90 additions & 0 deletions Command/WarmCacheCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace Liip\ImagineBundle\Command;

use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Liip\ImagineBundle\Imagine\Cache\CacheWarmer;
use Liip\ImagineBundle\Imagine\Data\DataManager;
use Liip\ImagineBundle\Imagine\Filter\FilterManager;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
* A command to warm up images cache (i.e. pre-generate thumbnails)
*
* @author Konstantin Tjuterev <[email protected]>
*/
class WarmCacheCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('liip:imagine:cache:warm')
->setDescription('Warms cache for paths provided by given warmers (or all warmers, if run w/o params)')
->addOption('chunk-size', 'c', InputOption::VALUE_REQUIRED, 'Chunk size', 100)
->addOption('force', 'f', InputOption::VALUE_NONE, 'Force cache warm up for already cached images')
->addArgument('warmers', InputArgument::OPTIONAL|InputArgument::IS_ARRAY, 'Warmers names')
->setHelp(<<<EOF
The <info>%command.name%</info> command warms up cache by specified parameters.

A warmer can be configured for one or more filter set. A warmer should return a list of paths.
This command gets the paths from warmer and create cache (i.e. filtered image) for each filter configured for given warmer.

Warmers should be separated by spaces:
<info>php app/console %command.name% warmer1 warmer2</info>
All cache for a given `warmers` will be warmed up

<info>php app/console %command.name%</info>
Cache for all warmers will be warmed up when executing this command without parameters.

Note, that <info>--force</info> option will force regeneration of the cache only if warmer returns the path.
Generally, there should be NO need to use this option, instead, use <info>liip:imagine:cache:remove</info> command to clear cache.
Then run this command to warm-up the cache
EOF
);
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$warmers = $input->getArgument('warmers');

/** @var CacheWarmer $cacheWarmer */
$cacheWarmer = $this->getContainer()->get('liip_imagine.cache.warmer');
$cacheWarmer->setLoggerClosure($this->getLoggerClosure($output));

if ($chunkSize = $input->getOption('chunk-size')) {
$cacheWarmer->setChunkSize($chunkSize);
}

$force = false;
if ($input->getOption('force')) {
$force = true;
}

$cacheWarmer->warm($force, $warmers);
}

/**
* Returns Logger Closure
*
* @return callable
*/
protected function getLoggerClosure(OutputInterface $output)
{
$loggerClosure = function ($message, $msgType = 'info') use ($output) {
$time = date('Y-m-d G:i:s');
$message = sprintf(
'<comment>%s | Mem cur/peak: %dm/%dm </comment> | <' . $msgType . '>%s</' . $msgType . '>',
$time,
round(memory_get_usage(true) / 1024 / 1024, 1),
round(memory_get_peak_usage(true) / 1024 / 1024, 1),
$message
);
$output->writeln($message);
};
return $loggerClosure;
}
}
26 changes: 26 additions & 0 deletions DependencyInjection/Compiler/CacheWarmersCompilerPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Liip\ImagineBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class CacheWarmersCompilerPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
$tags = $container->findTaggedServiceIds('liip_imagine.cache.warmer');

if (count($tags) > 0 && $container->hasDefinition('liip_imagine.cache.warmer')) {
$warmer = $container->getDefinition('liip_imagine.cache.warmer');

foreach ($tags as $id => $tag) {
$warmer->addMethodCall('addWarmer', array($tag[0]['warmer'], new Reference($id)));
}
}
}
}
6 changes: 6 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ public function getConfigTreeBuilder()
->useAttributeAsKey('name')
->prototype('variable')->end()
->end()
->end()
->arrayNode('warmers')
->defaultValue(array())
->useAttributeAsKey('name')
->prototype('scalar')
->end()
->end()
->end()
->end()
Expand Down
42 changes: 42 additions & 0 deletions DependencyInjection/Factory/Resolver/FormatResolverFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Liip\ImagineBundle\DependencyInjection\Factory\Resolver;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\DefinitionDecorator;

/**
* Class FormatResolverFactory
*
* @copyright 2017 IntechSystems, SIA
* @package Liip\ImagineBundle\DependencyInjection\Factory\Resolver
* @author Mihail Savluga
*/
class FormatResolverFactory extends WebPathResolverFactory
{
/**
* {@inheritDoc}
*/
public function create(ContainerBuilder $container, $resolverName, array $config)
{
$resolverDefinition = new DefinitionDecorator('liip_imagine.cache.resolver.prototype.format');
$resolverDefinition->replaceArgument(2, $config['web_root']);
$resolverDefinition->replaceArgument(3, $config['cache_prefix']);
$resolverDefinition->addTag('liip_imagine.cache.resolver', array(
'resolver' => $resolverName
));
$resolverId = 'liip_imagine.cache.resolver.'.$resolverName;

$container->setDefinition($resolverId, $resolverDefinition);

return $resolverId;
}

/**
* {@inheritDoc}
*/
public function getName()
{
return 'format';
}
}
19 changes: 19 additions & 0 deletions Imagine/Cache/CacheManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ class CacheManager
*/
protected $defaultResolver;

/**
* @var CacheWarmer
*/
protected $cacheWarmer;

/**
* @var bool
*/
Expand Down Expand Up @@ -95,6 +100,18 @@ public function addResolver($filter, ResolverInterface $resolver)
}
}

/**
* @param \Liip\ImagineBundle\Imagine\Cache\CacheWarmer $cacheWarmer
*
* @return CacheManager
*/
public function setCacheWarmer($cacheWarmer)
{
$this->cacheWarmer = $cacheWarmer;

return $this;
}

/**
* Gets filtered path for rendering in the browser.
* It could be the cached one or an url of filter action.
Expand Down Expand Up @@ -238,6 +255,8 @@ public function remove($paths = null, $filters = null)
$paths = array_filter($paths);
$filters = array_filter($filters);

$this->cacheWarmer->clearWarmed($paths, $filters);

$mapping = new \SplObjectStorage();
foreach ($filters as $filter) {
$resolver = $this->getResolver($filter, null);
Expand Down
Loading