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

Add symfony cache pool support #948

Merged
merged 2 commits into from
Apr 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use function array_key_exists;
use function is_array;

/**
* This class contains the configuration information for the bundle
Expand Down Expand Up @@ -687,18 +689,27 @@ private function getOrmCacheDriverNode($name)
->addDefaultsIfNotSet()
->beforeNormalization()
->ifString()
->then(static function ($v) {
->then(static function ($v) : array {
return ['type' => $v];
})
->end()
->beforeNormalization()
->ifTrue(static function ($v) : bool {
return is_array($v) && array_key_exists('cache_provider', $v);
})
->then(static function ($v) : array {
return ['type' => 'provider'] + $v;
})
->end()
->children()
->scalarNode('type')->defaultValue('array')->end()
->scalarNode('id')->end()
->scalarNode('pool')->end()
->scalarNode('host')->end()
->scalarNode('port')->end()
->scalarNode('database')->end()
->scalarNode('instance_class')->end()
->scalarNode('class')->end()
->scalarNode('id')->end()
->scalarNode('namespace')->defaultNull()->end()
->scalarNode('cache_provider')->defaultNull()->end()
->end();
Expand Down
38 changes: 35 additions & 3 deletions DependencyInjection/DoctrineExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Symfony\Bridge\Doctrine\Messenger\DoctrineTransactionMiddleware;
use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor;
use Symfony\Bridge\Doctrine\Validator\DoctrineLoader;
use Symfony\Component\Cache\DoctrineProvider;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ChildDefinition;
Expand All @@ -24,6 +25,8 @@
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Transport\Doctrine\DoctrineTransportFactory;
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
use function class_exists;
use function sprintf;

/**
* DoctrineExtension is an extension for the Doctrine DBAL and ORM library.
Expand Down Expand Up @@ -707,10 +710,24 @@ protected function getMappingResourceExtension()
*/
protected function loadCacheDriver($driverName, $entityManagerName, array $driverMap, ContainerBuilder $container)
{
if (! empty($driverMap['cache_provider'])) {
$aliasId = $this->getObjectManagerElementName(sprintf('%s_%s', $entityManagerName, $driverName));
$serviceId = sprintf('doctrine_cache.providers.%s', $driverMap['cache_provider']);
$serviceId = null;
$aliasId = $this->getObjectManagerElementName(sprintf('%s_%s', $entityManagerName, $driverName));

switch ($driverMap['type']) {
case 'service':
$serviceId = $driverMap['id'];
break;

case 'pool':
$serviceId = $this->createPoolCacheDefinition($container, $aliasId, $driverMap['pool']);
break;

case 'provider':
$serviceId = sprintf('doctrine_cache.providers.%s', $driverMap['cache_provider']);
break;
}

if ($serviceId !== null) {
$container->setAlias($aliasId, new Alias($serviceId, false));

return $aliasId;
Expand Down Expand Up @@ -824,4 +841,19 @@ private function loadMessengerServices(ContainerBuilder $container) : void
$transportFactoryDefinition = $container->getDefinition('messenger.transport.doctrine.factory');
$transportFactoryDefinition->addTag('messenger.transport_factory');
}

private function createPoolCacheDefinition(ContainerBuilder $container, string $aliasId, string $poolName) : string
{
if (! class_exists(DoctrineProvider::class)) {
throw new LogicException('Using the "pool" cache type is only supported when symfony/cache is installed.');
}

$serviceId = sprintf('doctrine.orm.cache.pool.%s', $poolName);

$definition = $container->register($aliasId, DoctrineProvider::class);
$definition->addArgument(new Reference($poolName));
$definition->setPrivate(true);

return $serviceId;
}
}
58 changes: 40 additions & 18 deletions Resources/doc/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -273,29 +273,32 @@ Configuration Reference
some_em:
query_cache_driver:
type: array
id: ~
pool: ~
host: ~
port: ~
instance_class: ~
class: ~
id: ~
namespace: ~
cache_provider: ~
metadata_cache_driver:
type: array
id: ~
pool: ~
host: ~
port: ~
instance_class: ~
class: ~
id: ~
namespace: ~
cache_provider: ~
result_cache_driver:
type: array
id: ~
pool: ~
host: ~
port: ~
instance_class: ~
class: ~
id: ~
namespace: ~
cache_provider: ~
entity_listeners:
Expand Down Expand Up @@ -323,11 +326,12 @@ Configuration Reference
second_level_cache:
region_cache_driver:
type: array
pool: ~
id: ~
host: ~
port: ~
instance_class: ~
class: ~
id: ~
namespace: ~
cache_provider: ~
region_lock_lifetime: 60
Expand All @@ -341,11 +345,12 @@ Configuration Reference
name:
cache_driver:
type: array
id: ~
pool: ~
host: ~
port: ~
instance_class: ~
class: ~
id: ~
namespace: ~
cache_provider: ~
lock_path: '%kernel.cache_dir%/doctrine/orm/slc/filelock'
Expand Down Expand Up @@ -621,33 +626,36 @@ Configuration Reference

<doctrine:query-cache-driver
type="array"
id=""
pool=""
host=""
port=""
instance-class=""
class=""
id=""
namespace="null"
cache-provider="null"
/>

<doctrine:metadata-cache-driver
type="memcache"
id=""
pool=""
host="localhost"
port="11211"
instance-class="Memcache"
class="Doctrine\Common\Cache\MemcacheCache"
id=""
namespace="null"
cache-provider="null"
/>

<doctrine:result-cache-driver
type="array"
id=""
pool=""
host=""
port=""
instance-class=""
class=""
id=""
namespace="null"
cache-provider="null"
/>
Expand Down Expand Up @@ -682,11 +690,12 @@ Configuration Reference

<doctrine:region-cache-driver
type="array"
id=""
pool=""
host=""
port=""
instance-class=""
class=""
id=""
namespace="null"
cache-provider="null"
/>
Expand All @@ -703,11 +712,12 @@ Configuration Reference

<doctrine:cache-driver
type="array"
id=""
pool=""
host=""
port=""
instance-class=""
class=""
id=""
namespace="null"
cache-provider="null"
/>
Expand Down Expand Up @@ -825,8 +835,11 @@ The environment variables that doctrine is going to change in the Oracle DB sess
Caching Drivers
~~~~~~~~~~~~~~~

For the caching drivers you can specify the values ``array``, ``apc``, ``apcu``, ``memcache``,
``memcached`` or ``xcache``.
For the caching drivers you can specify the values ``array``, ``apc``, ``apcu``,
``memcache``, ``memcached``, ``redis``, ``wincache``, ``zenddata`` and
``xcache``. You can use a Symfony Cache pool by using the ``pool`` type and
creating a cache bool through the FrameworkBundle configuration. The ``service``
type lets you define the ``ID`` of your own caching service.

The following example shows an overview of the caching configurations:

Expand All @@ -835,13 +848,22 @@ The following example shows an overview of the caching configurations:
doctrine:
orm:
auto_mapping: true
metadata_cache_driver: apcu
query_cache_driver: xcache
# each caching driver type defines its own config options
metadata_cache_driver: apc
# the 'pool' type requires to define the 'pool' option and configure a cache pool using the FrameworkBundle
result_cache_driver:
type: memcache
host: localhost
port: 11211
instance_class: Memcache
type: pool
pool: doctrine.result_cache_pool
# the 'service' type requires to define the 'id' option too
query_cache_driver:
type: service
id: App\ORM\MyCacheService

framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app

Mapping Configuration
~~~~~~~~~~~~~~~~~~~~~
Expand Down
87 changes: 71 additions & 16 deletions Tests/DependencyInjection/DoctrineExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -665,33 +665,88 @@ public function testMessengerIntegration()
$this->assertCount(1, $middlewarePrototype->getArguments());
}

public function testCacheConfiguration()
/**
* @param array|string $cacheConfig
*
* @dataProvider cacheConfigurationProvider
*/
public function testCacheConfiguration(string $expectedAliasName, string $expectedAliasTarget, string $cacheName, $cacheConfig) : void
{
$container = $this->getContainer();
$extension = new DoctrineExtension();

$config = BundleConfigurationBuilder::createBuilder()
->addBaseConnection()
->addEntityManager([
'metadata_cache_driver' => ['cache_provider' => 'metadata_cache'],
'query_cache_driver' => ['cache_provider' => 'query_cache'],
'result_cache_driver' => ['cache_provider' => 'result_cache'],
])
->addBaseConnection()
->addEntityManager([$cacheName => $cacheConfig])
->build();

$extension->load([$config], $container);

$this->assertTrue($container->hasAlias('doctrine.orm.default_metadata_cache'));
$alias = $container->getAlias('doctrine.orm.default_metadata_cache');
$this->assertEquals('doctrine_cache.providers.metadata_cache', (string) $alias);
$this->assertTrue($container->hasAlias($expectedAliasName));
$alias = $container->getAlias($expectedAliasName);
$this->assertEquals($expectedAliasTarget, (string) $alias);
}

public static function cacheConfigurationProvider() : array
{
return [
'metadata_cache_provider' => [
'expectedAliasName' => 'doctrine.orm.default_metadata_cache',
'expectedAliasTarget' => 'doctrine_cache.providers.metadata_cache',
'cacheName' => 'metadata_cache_driver',
'cacheConfig' => ['cache_provider' => 'metadata_cache'],
],
'query_cache_provider' => [
'expectedAliasName' => 'doctrine.orm.default_query_cache',
'expectedAliasTarget' => 'doctrine_cache.providers.query_cache',
'cacheName' => 'query_cache_driver',
'cacheConfig' => ['cache_provider' => 'query_cache'],
],
'result_cache_provider' => [
'expectedAliasName' => 'doctrine.orm.default_result_cache',
'expectedAliasTarget' => 'doctrine_cache.providers.result_cache',
'cacheName' => 'result_cache_driver',
'cacheConfig' => ['cache_provider' => 'result_cache'],
],

$this->assertTrue($container->hasAlias('doctrine.orm.default_query_cache'));
$alias = $container->getAlias('doctrine.orm.default_query_cache');
$this->assertEquals('doctrine_cache.providers.query_cache', (string) $alias);
'metadata_cache_service' => [
'expectedAliasName' => 'doctrine.orm.default_metadata_cache',
'expectedAliasTarget' => 'service_target_metadata',
'cacheName' => 'metadata_cache_driver',
'cacheConfig' => ['type' => 'service', 'id' => 'service_target_metadata'],
],
'query_cache_service' => [
'expectedAliasName' => 'doctrine.orm.default_query_cache',
'expectedAliasTarget' => 'service_target_query',
'cacheName' => 'query_cache_driver',
'cacheConfig' => ['type' => 'service', 'id' => 'service_target_query'],
],
'result_cache_service' => [
'expectedAliasName' => 'doctrine.orm.default_result_cache',
'expectedAliasTarget' => 'service_target_result',
'cacheName' => 'result_cache_driver',
'cacheConfig' => ['type' => 'service', 'id' => 'service_target_result'],
],

$this->assertTrue($container->hasAlias('doctrine.orm.default_result_cache'));
$alias = $container->getAlias('doctrine.orm.default_result_cache');
$this->assertEquals('doctrine_cache.providers.result_cache', (string) $alias);
'metadata_cache_array' => [
'expectedAliasName' => 'doctrine.orm.default_metadata_cache',
'expectedAliasTarget' => 'doctrine_cache.providers.doctrine.orm.default_metadata_cache',
'cacheName' => 'metadata_cache_driver',
'cacheConfig' => 'array',
],
'query_cache_array' => [
'expectedAliasName' => 'doctrine.orm.default_query_cache',
'expectedAliasTarget' => 'doctrine_cache.providers.doctrine.orm.default_query_cache',
'cacheName' => 'query_cache_driver',
'cacheConfig' => 'array',
],
'result_cache_array' => [
'expectedAliasName' => 'doctrine.orm.default_result_cache',
'expectedAliasTarget' => 'doctrine_cache.providers.doctrine.orm.default_result_cache',
'cacheName' => 'result_cache_driver',
'cacheConfig' => 'array',
],
];
}

public function testShardManager()
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
},
"require-dev": {
"doctrine/orm": "^2.6",
"symfony/cache": "^3.4|^4.1",
"symfony/yaml": "^3.4|^4.1",
"symfony/validator": "^3.4|^4.1",
"symfony/property-info": "^3.4|^4.1",
Expand Down