feature #26934 [FrameworkBundle] Allow configuring taggable cache pools (nicolas-grekas)
This PR was merged into the 4.2-dev branch.
Discussion
----------
[FrameworkBundle] Allow configuring taggable cache pools
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #25903
| License | MIT
| Doc PR | https://github.com/symfony/symfony-docs/pull/9652
This PR adds a new configuration option for cache pools:
```yaml
framework:
cache:
pools:
app.taggable_pool:
tags: true
app.taggable_pool_with_separate_store_for_tags:
tags: app.my_pool_for_tags
```
Commits
-------
896be4cc2b
[FrameworkBundle] Allow configuring taggable cache pools
This commit is contained in:
commit
143628fa51
@ -1,6 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* Allowed configuring taggable cache pools via a new `framework.cache.pools.tags` option (bool|service-id)
|
||||
|
||||
4.1.0
|
||||
-----
|
||||
|
||||
|
@ -31,9 +31,9 @@ final class CachePoolClearerPass implements CompilerPassInterface
|
||||
foreach ($container->findTaggedServiceIds('cache.pool.clearer') as $id => $attr) {
|
||||
$clearer = $container->getDefinition($id);
|
||||
$pools = array();
|
||||
foreach ($clearer->getArgument(0) as $id => $ref) {
|
||||
if ($container->hasDefinition($id)) {
|
||||
$pools[$id] = new Reference($id);
|
||||
foreach ($clearer->getArgument(0) as $name => $ref) {
|
||||
if ($container->hasDefinition($ref)) {
|
||||
$pools[$name] = new Reference($ref);
|
||||
}
|
||||
}
|
||||
$clearer->replaceArgument(0, $pools);
|
||||
|
@ -41,6 +41,7 @@ class CachePoolPass implements CompilerPassInterface
|
||||
$clearers = array();
|
||||
$attributes = array(
|
||||
'provider',
|
||||
'name',
|
||||
'namespace',
|
||||
'default_lifetime',
|
||||
'reset',
|
||||
@ -56,8 +57,9 @@ class CachePoolPass implements CompilerPassInterface
|
||||
$tags[0] += $t[0];
|
||||
}
|
||||
}
|
||||
$name = $tags[0]['name'] ?? $id;
|
||||
if (!isset($tags[0]['namespace'])) {
|
||||
$tags[0]['namespace'] = $this->getNamespace($seed, $id);
|
||||
$tags[0]['namespace'] = $this->getNamespace($seed, $name);
|
||||
}
|
||||
if (isset($tags[0]['clearer'])) {
|
||||
$clearer = $tags[0]['clearer'];
|
||||
@ -67,7 +69,7 @@ class CachePoolPass implements CompilerPassInterface
|
||||
} else {
|
||||
$clearer = null;
|
||||
}
|
||||
unset($tags[0]['clearer']);
|
||||
unset($tags[0]['clearer'], $tags[0]['name']);
|
||||
|
||||
if (isset($tags[0]['provider'])) {
|
||||
$tags[0]['provider'] = new Reference(static::getServiceProvider($container, $tags[0]['provider']));
|
||||
@ -86,14 +88,14 @@ class CachePoolPass implements CompilerPassInterface
|
||||
unset($tags[0][$attr]);
|
||||
}
|
||||
if (!empty($tags[0])) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "namespace", "default_lifetime" and "reset", found "%s".', $id, implode('", "', array_keys($tags[0]))));
|
||||
throw new InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "name", "namespace", "default_lifetime" and "reset", found "%s".', $id, implode('", "', array_keys($tags[0]))));
|
||||
}
|
||||
|
||||
if (null !== $clearer) {
|
||||
$clearers[$clearer][$id] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
|
||||
$clearers[$clearer][$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
|
||||
}
|
||||
|
||||
$pools[$id] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
|
||||
$pools[$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
|
||||
}
|
||||
|
||||
$clearer = 'cache.global_clearer';
|
||||
|
@ -870,6 +870,7 @@ class Configuration implements ConfigurationInterface
|
||||
->prototype('array')
|
||||
->children()
|
||||
->scalarNode('adapter')->defaultValue('cache.app')->end()
|
||||
->scalarNode('tags')->defaultNull()->end()
|
||||
->booleanNode('public')->defaultFalse()->end()
|
||||
->integerNode('default_lifetime')->end()
|
||||
->scalarNode('provider')
|
||||
|
@ -22,6 +22,7 @@ use Symfony\Bundle\FullStack;
|
||||
use Symfony\Component\Cache\Adapter\AbstractAdapter;
|
||||
use Symfony\Component\Cache\Adapter\AdapterInterface;
|
||||
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
||||
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
|
||||
use Symfony\Component\Cache\ResettableInterface;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||
@ -1556,12 +1557,31 @@ class FrameworkExtension extends Extension
|
||||
$config['pools']['cache.'.$name] = array(
|
||||
'adapter' => $config[$name],
|
||||
'public' => true,
|
||||
'tags' => false,
|
||||
);
|
||||
}
|
||||
foreach ($config['pools'] as $name => $pool) {
|
||||
if ($config['pools'][$pool['adapter']]['tags'] ?? false) {
|
||||
$pool['adapter'] = '.'.$pool['adapter'].'.inner';
|
||||
}
|
||||
$definition = new ChildDefinition($pool['adapter']);
|
||||
|
||||
if ($pool['tags']) {
|
||||
if ($config['pools'][$pool['tags']]['tags'] ?? false) {
|
||||
$pool['tags'] = '.'.$pool['tags'].'.inner';
|
||||
}
|
||||
$container->register($name, TagAwareAdapter::class)
|
||||
->addArgument(new Reference('.'.$name.'.inner'))
|
||||
->addArgument(true !== $pool['tags'] ? new Reference($pool['tags']) : null)
|
||||
->setPublic($pool['public'])
|
||||
;
|
||||
|
||||
$pool['name'] = $name;
|
||||
$pool['public'] = false;
|
||||
$name = '.'.$name.'.inner';
|
||||
}
|
||||
$definition->setPublic($pool['public']);
|
||||
unset($pool['adapter'], $pool['public']);
|
||||
unset($pool['adapter'], $pool['public'], $pool['tags']);
|
||||
|
||||
$definition->addTag('cache.pool', $pool);
|
||||
$container->setDefinition($name, $definition);
|
||||
|
@ -39,6 +39,11 @@ class CachePoolClearerPassTest extends TestCase
|
||||
$publicPool->addTag('cache.pool', array('clearer' => 'clearer_alias'));
|
||||
$container->setDefinition('public.pool', $publicPool);
|
||||
|
||||
$publicPool = new Definition();
|
||||
$publicPool->addArgument('namespace');
|
||||
$publicPool->addTag('cache.pool', array('clearer' => 'clearer_alias', 'name' => 'pool2'));
|
||||
$container->setDefinition('public.pool2', $publicPool);
|
||||
|
||||
$privatePool = new Definition();
|
||||
$privatePool->setPublic(false);
|
||||
$privatePool->addArgument('namespace');
|
||||
@ -55,7 +60,11 @@ class CachePoolClearerPassTest extends TestCase
|
||||
$pass->process($container);
|
||||
}
|
||||
|
||||
$this->assertEquals(array(array('public.pool' => new Reference('public.pool'))), $clearer->getArguments());
|
||||
$this->assertEquals(array(array('public.pool' => new Reference('public.pool'))), $globalClearer->getArguments());
|
||||
$expected = array(array(
|
||||
'public.pool' => new Reference('public.pool'),
|
||||
'pool2' => new Reference('public.pool2'),
|
||||
));
|
||||
$this->assertEquals($expected, $clearer->getArguments());
|
||||
$this->assertEquals($expected, $globalClearer->getArguments());
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,28 @@ class CachePoolPassTest extends TestCase
|
||||
$this->assertSame(3, $cachePool->getArgument(2));
|
||||
}
|
||||
|
||||
public function testWithNameAttribute()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->setParameter('kernel.debug', false);
|
||||
$container->setParameter('kernel.name', 'app');
|
||||
$container->setParameter('kernel.environment', 'prod');
|
||||
$container->setParameter('cache.prefix.seed', 'foo');
|
||||
$cachePool = new Definition();
|
||||
$cachePool->addTag('cache.pool', array(
|
||||
'name' => 'foobar',
|
||||
'provider' => 'foobar',
|
||||
));
|
||||
$cachePool->addArgument(null);
|
||||
$cachePool->addArgument(null);
|
||||
$cachePool->addArgument(null);
|
||||
$container->setDefinition('app.cache_pool', $cachePool);
|
||||
|
||||
$this->cachePoolPass->process($container);
|
||||
|
||||
$this->assertSame('9HvPgAayyh', $cachePool->getArgument(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Invalid "cache.pool" tag for service "app.cache_pool": accepted attributes are
|
||||
|
@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
|
||||
|
||||
use Symfony\Component\Cache\Adapter\AdapterInterface;
|
||||
use Symfony\Component\Cache\Adapter\RedisAdapter;
|
||||
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
|
||||
use Symfony\Component\Cache\Exception\InvalidArgumentException;
|
||||
|
||||
class CachePoolsTest extends WebTestCase
|
||||
@ -94,6 +95,25 @@ class CachePoolsTest extends WebTestCase
|
||||
|
||||
$item = $pool2->getItem($key);
|
||||
$this->assertTrue($item->isHit());
|
||||
|
||||
$prefix = "\0".TagAwareAdapter::class."\0";
|
||||
$pool4 = $container->get('cache.pool4');
|
||||
$this->assertInstanceof(TagAwareAdapter::class, $pool4);
|
||||
$pool4 = (array) $pool4;
|
||||
$this->assertSame($pool4[$prefix.'pool'], $pool4[$prefix.'tags'] ?? $pool4['tags']);
|
||||
|
||||
$pool5 = $container->get('cache.pool5');
|
||||
$this->assertInstanceof(TagAwareAdapter::class, $pool5);
|
||||
$pool5 = (array) $pool5;
|
||||
$this->assertSame($pool2, $pool5[$prefix.'tags'] ?? $pool5['tags']);
|
||||
|
||||
$pool6 = $container->get('cache.pool6');
|
||||
$this->assertInstanceof(TagAwareAdapter::class, $pool6);
|
||||
$pool6 = (array) $pool6;
|
||||
$this->assertSame($pool4[$prefix.'pool'], $pool6[$prefix.'tags'] ?? $pool6['tags']);
|
||||
|
||||
$pool7 = $container->get('cache.pool7');
|
||||
$this->assertNotInstanceof(TagAwareAdapter::class, $pool7);
|
||||
}
|
||||
|
||||
protected static function createKernel(array $options = array())
|
||||
|
@ -12,3 +12,15 @@ framework:
|
||||
adapter: cache.pool3
|
||||
cache.pool3:
|
||||
clearer: ~
|
||||
cache.pool4:
|
||||
tags: true
|
||||
public: true
|
||||
cache.pool5:
|
||||
tags: cache.pool2
|
||||
public: true
|
||||
cache.pool6:
|
||||
tags: cache.pool4
|
||||
public: true
|
||||
cache.pool7:
|
||||
adapter: cache.pool4
|
||||
public: true
|
||||
|
@ -15,3 +15,17 @@ framework:
|
||||
cache.pool2:
|
||||
public: true
|
||||
clearer: ~
|
||||
cache.pool3:
|
||||
clearer: ~
|
||||
cache.pool4:
|
||||
tags: true
|
||||
public: true
|
||||
cache.pool5:
|
||||
tags: cache.pool2
|
||||
public: true
|
||||
cache.pool6:
|
||||
tags: cache.pool4
|
||||
public: true
|
||||
cache.pool7:
|
||||
adapter: cache.pool4
|
||||
public: true
|
||||
|
@ -26,3 +26,17 @@ framework:
|
||||
cache.pool2:
|
||||
public: true
|
||||
clearer: ~
|
||||
cache.pool3:
|
||||
clearer: ~
|
||||
cache.pool4:
|
||||
tags: true
|
||||
public: true
|
||||
cache.pool5:
|
||||
tags: cache.pool2
|
||||
public: true
|
||||
cache.pool6:
|
||||
tags: cache.pool4
|
||||
public: true
|
||||
cache.pool7:
|
||||
adapter: cache.pool4
|
||||
public: true
|
||||
|
Reference in New Issue
Block a user