Skip to content

Commit

Permalink
feature #18544 [FrameworkBundle] Fallback to default cache system in …
Browse files Browse the repository at this point in the history
…production for validation (tgalopin)

This PR was merged into the 3.1-dev branch.

Discussion
----------

[FrameworkBundle] Fallback to default cache system in production for validation

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | WIP
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

This PR proposes a default fallback to filesystem cache for some services if the APC cache is not enabled in production. In other words, if the following part of `config_prod.yml` file is not uncommented, the filesystem will be used:

``` yaml
#framework:
#    validation:
#        cache: validator.mapping.cache.doctrine.apc
#    serializer:
#        cache: serializer.mapping.cache.doctrine.apc
#
# ... other services
```

Commits
-------

1a65595 [FrameworkBundle] Fallback to default cache system in production for validation
  • Loading branch information
fabpot committed Apr 15, 2016
2 parents 8d6670b + 1a65595 commit e4177a7
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 19 deletions.
Expand Up @@ -26,6 +26,14 @@ class CachePoolPass implements CompilerPassInterface
*/
public function process(ContainerBuilder $container)
{
$namespaceSuffix = '';

foreach (array('name', 'root_dir', 'environment', 'debug') as $key) {
if ($container->hasParameter('kernel.'.$key)) {
$namespaceSuffix .= '.'.$container->getParameter('kernel.'.$key);
}
}

$attributes = array(
'provider',
'namespace',
Expand All @@ -36,9 +44,7 @@ public function process(ContainerBuilder $container)
if ($pool->isAbstract()) {
continue;
}
if (!isset($tags[0]['namespace'])) {
$tags[0]['namespace'] = $this->getNamespace($id);
}
$tags[0]['namespace'] = $this->getNamespace($namespaceSuffix, isset($tags[0]['namespace']) ? $tags[0]['namespace'] : $id);
while ($adapter instanceof DefinitionDecorator) {
$adapter = $container->findDefinition($adapter->getParent());
if ($t = $adapter->getTag('cache.pool')) {
Expand Down Expand Up @@ -72,8 +78,8 @@ public function process(ContainerBuilder $container)
}
}

private function getNamespace($id)
private function getNamespace($namespaceSuffix, $id)
{
return substr(str_replace('/', '-', base64_encode(md5('symfony.'.$id, true))), 0, 10);
return substr(str_replace('/', '-', base64_encode(md5($id.$namespaceSuffix, true))), 0, 10);
}
}
Expand Up @@ -468,7 +468,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode)
->info('validation configuration')
->canBeEnabled()
->children()
->scalarNode('cache')->end()
->scalarNode('cache')->defaultValue('validator.mapping.cache.symfony')->end()
->booleanNode('enable_annotations')->defaultFalse()->end()
->arrayNode('static_method')
->defaultValue(array('loadValidatorMetadata'))
Expand Down
Expand Up @@ -71,6 +71,9 @@ public function load(array $configs, ContainerBuilder $container)
// Property access is used by both the Form and the Validator component
$loader->load('property_access.xml');

// Load Cache configuration first as it is used by other components
$loader->load('cache_pools.xml');

$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);

Expand Down Expand Up @@ -781,7 +784,7 @@ private function registerValidationConfiguration(array $config, ContainerBuilder
}
}

if (isset($config['cache'])) {
if (!$container->getParameter('kernel.debug')) {
$container->setParameter(
'validator.mapping.cache.prefix',
'validator_'.$this->getKernelRootHash($container)
Expand Down Expand Up @@ -1019,8 +1022,6 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild

private function registerCacheConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
{
$loader->load('cache_pools.xml');

foreach ($config['pools'] as $name => $poolConfig) {
$poolDefinition = new DefinitionDecorator($poolConfig['adapter']);
$poolDefinition->setPublic($poolConfig['public']);
Expand Down
Expand Up @@ -21,6 +21,10 @@
<tag name="cache.pool" clearer="cache.default_pools_clearer" />
</service>

<service id="cache.pool.validator" parent="cache.adapter.local" public="false">
<tag name="cache.pool" clearer="cache.default_pools_clearer" />
</service>

<service id="cache.adapter.apcu" class="Symfony\Component\Cache\Adapter\ApcuAdapter" abstract="true">
<argument /> <!-- namespace -->
<argument /> <!-- default lifetime -->
Expand Down
Expand Up @@ -28,6 +28,10 @@

<service id="validator.mapping.class_metadata_factory" alias="validator" public="false" />

<service id="validator.mapping.cache.symfony" class="Symfony\Component\Validator\Mapping\Cache\Psr6Cache" public="false">
<argument type="service" id="cache.pool.validator" />
</service>

<service id="validator.mapping.cache.doctrine.apc" class="Symfony\Component\Validator\Mapping\Cache\DoctrineCache" public="false">
<argument type="service">
<service class="Doctrine\Common\Cache\ApcCache">
Expand Down
Expand Up @@ -41,7 +41,7 @@ public function testNamespaceArgumentIsReplaced()

$this->cachePoolPass->process($container);

$this->assertSame('yRnzIIVLvL', $cachePool->getArgument(0));
$this->assertSame('VcRIZlUhEv', $cachePool->getArgument(0));
}

public function testArgsAreReplaced()
Expand All @@ -61,7 +61,7 @@ public function testArgsAreReplaced()

$this->assertInstanceOf(Reference::class, $cachePool->getArgument(0));
$this->assertSame('foobar', (string) $cachePool->getArgument(0));
$this->assertSame('yRnzIIVLvL', $cachePool->getArgument(1));
$this->assertSame('VcRIZlUhEv', $cachePool->getArgument(1));
$this->assertSame(3, $cachePool->getArgument(2));
}

Expand Down
Expand Up @@ -211,6 +211,7 @@ protected static function getBundleDefaultConfig()
'static_method' => array('loadValidatorMetadata'),
'translation_domain' => 'validators',
'strict_email' => false,
'cache' => 'validator.mapping.cache.symfony',
),
'annotations' => array(
'cache' => 'file',
Expand Down
Expand Up @@ -323,7 +323,7 @@ public function testValidation()

public function testValidationService()
{
$container = $this->createContainerFromFile('validation_annotations');
$container = $this->createContainerFromFile('validation_annotations', array('kernel.charset' => 'UTF-8'), false);

$this->assertInstanceOf('Symfony\Component\Validator\Validator\ValidatorInterface', $container->get('validator'));
}
Expand All @@ -350,11 +350,13 @@ public function testValidationAnnotations()

$calls = $container->getDefinition('validator.builder')->getMethodCalls();

$this->assertCount(6, $calls);
$this->assertCount(7, $calls);
$this->assertSame('enableAnnotationMapping', $calls[4][0]);
$this->assertEquals(array(new Reference('annotation_reader')), $calls[4][1]);
$this->assertSame('addMethodMapping', $calls[5][0]);
$this->assertSame(array('loadValidatorMetadata'), $calls[5][1]);
$this->assertSame('setMetadataCache', $calls[6][0]);
$this->assertEquals(array(new Reference('validator.mapping.cache.symfony')), $calls[6][1]);
// no cache this time
}

Expand All @@ -368,12 +370,14 @@ public function testValidationPaths()

$calls = $container->getDefinition('validator.builder')->getMethodCalls();

$this->assertCount(7, $calls);
$this->assertCount(8, $calls);
$this->assertSame('addXmlMappings', $calls[3][0]);
$this->assertSame('addYamlMappings', $calls[4][0]);
$this->assertSame('enableAnnotationMapping', $calls[5][0]);
$this->assertSame('addMethodMapping', $calls[6][0]);
$this->assertSame(array('loadValidatorMetadata'), $calls[6][1]);
$this->assertSame('setMetadataCache', $calls[7][0]);
$this->assertEquals(array(new Reference('validator.mapping.cache.symfony')), $calls[7][1]);

$xmlMappings = $calls[3][1][0];
$this->assertCount(2, $xmlMappings);
Expand All @@ -397,8 +401,10 @@ public function testValidationNoStaticMethod()

$calls = $container->getDefinition('validator.builder')->getMethodCalls();

$this->assertCount(4, $calls);
$this->assertCount(5, $calls);
$this->assertSame('addXmlMappings', $calls[3][0]);
$this->assertSame('setMetadataCache', $calls[4][0]);
$this->assertEquals(array(new Reference('validator.mapping.cache.symfony')), $calls[4][1]);
// no cache, no annotations, no static methods
}

Expand Down Expand Up @@ -594,7 +600,7 @@ protected function createContainer(array $data = array())
), $data)));
}

protected function createContainerFromFile($file, $data = array())
protected function createContainerFromFile($file, $data = array(), $resetCompilerPasses = true)
{
$cacheKey = md5(get_class($this).$file.serialize($data));
if (isset(self::$containerCache[$cacheKey])) {
Expand All @@ -604,8 +610,10 @@ protected function createContainerFromFile($file, $data = array())
$container->registerExtension(new FrameworkExtension());
$this->loadFromFile($container, $file);

$container->getCompilerPassConfig()->setOptimizationPasses(array());
$container->getCompilerPassConfig()->setRemovingPasses(array());
if ($resetCompilerPasses) {
$container->getCompilerPassConfig()->setOptimizationPasses(array());
$container->getCompilerPassConfig()->setRemovingPasses(array());
}
$container->compile();

return self::$containerCache[$cacheKey] = $container;
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bundle/FrameworkBundle/composer.json
Expand Up @@ -48,7 +48,7 @@
"symfony/expression-language": "~2.8|~3.0",
"symfony/process": "~2.8|~3.0",
"symfony/serializer": "~2.8|^3.0",
"symfony/validator": "~2.8|~3.0",
"symfony/validator": "~3.1",
"symfony/yaml": "~2.8|~3.0",
"symfony/property-info": "~2.8|~3.0",
"phpdocumentor/reflection-docblock": "^3.0",
Expand Down

0 comments on commit e4177a7

Please sign in to comment.