Skip to content
Permalink
Browse files

OrmCacheExtension: use autowired cache

  • Loading branch information
mabar authored and f3l1x committed Nov 25, 2019
1 parent 5b3a4b6 commit 8f0bf73e0c339200d906c45cd296e702055a4f55
Showing with 181 additions and 176 deletions.
  1. +9 −17 .docs/README.md
  2. +1 −1 composer.json
  3. +0 −72 src/DI/Helpers/CacheBuilder.php
  4. +98 −80 src/DI/OrmCacheExtension.php
  5. +73 −6 tests/cases/Unit/DI/OrmCacheExtensionTest.php
@@ -146,38 +146,30 @@ orm.xml:

This extension sets up cache for all important parts: `queryCache`, `resultCache`, `hydrationCache`, `metadataCache` and `secondLevelCache`.

This is the default configuration, it uses the `filesystem` driver.
This is the default configuration, it uses the autowired driver.

```yaml
extensions:
orm: Nettrine\ORM\DI\OrmExtension
orm.cache: Nettrine\ORM\DI\OrmCacheExtension
orm.cache:
defaultDriver: filesystem
```

Available drivers:

- `apc` - `ApcCache`
- `apcu` - `ApcuCache`
- `array` - `ArrayCache`
- `filesystem` - `FilesystemCache`
- `memcache` - `MemcacheCache`
- `memcached` - `MemcachedCache`
- `redis` - `RedisCache`
- `void` - `VoidCache`
- `xcache` - `XcacheCache`

You can also specify a single driver. Or change the `orm.cache.defaultDriver` for all of them.

```yaml
orm.cache:
defaultDriver: App\DefaultOrmCacheDriver
queryCache: App\SpecialDriver
resultCache: App\SpecialOtherDriver
hydrationCache: App\SpecialDriver('foo')
metadataCache: @cacheDriver
secondLevelCache: @cacheDriverFactory::create('bar')
```

`secondLevelCache` uses autowired driver (or `defaultDriver`, if specified) for `CacheConfiguration` setup, but you can also replace it with custom `CacheConfiguration`

```yaml
orm.cache:
secondLevelCache: @cacheConfigurationFactory::create('bar')
```

### Console Bridge
@@ -17,7 +17,7 @@
],
"require": {
"php": "^7.2",
"nette/di": "~3.0.0",
"contributte/di": "^0.4.0",
"nette/utils": "~3.0.1",
"symfony/console": "^4.2.5|^5.0.0",
"nettrine/dbal": "^0.5.0 || ^0.6.0",

This file was deleted.

@@ -2,13 +2,15 @@

namespace Nettrine\ORM\DI;

use Contributte\DI\Helper\ExtensionDefinitionsHelper;
use Doctrine\Common\Cache\Cache;
use Doctrine\ORM\Cache\CacheConfiguration;
use Doctrine\ORM\Cache\DefaultCacheFactory;
use Doctrine\ORM\Cache\RegionsConfiguration;
use Nette\InvalidStateException;
use Nette\DI\Definitions\Definition;
use Nette\DI\Definitions\Statement;
use Nette\Schema\Expect;
use Nette\Schema\Schema;
use Nettrine\ORM\DI\Helpers\CacheBuilder;
use stdClass;

/**
@@ -17,14 +19,26 @@
class OrmCacheExtension extends AbstractExtension
{

/** @var Definition|string|null */
private $defaultDriverDef;

private function getServiceSchema(): Schema
{
return Expect::anyOf(
Expect::string(),
Expect::array(),
Expect::type(Statement::class)
)->nullable();
}

public function getConfigSchema(): Schema
{
return Expect::structure([
'defaultDriver' => Expect::string('filesystem')->nullable(),
'queryCache' => Expect::string(),
'hydrationCache' => Expect::string(),
'metadataCache' => Expect::string(),
'resultCache' => Expect::string(),
'defaultDriver' => $this->getServiceSchema(),
'queryCache' => $this->getServiceSchema(),
'hydrationCache' => $this->getServiceSchema(),
'metadataCache' => $this->getServiceSchema(),
'resultCache' => $this->getServiceSchema(),
'secondLevelCache' => Expect::array()->default(null),
]);
}
@@ -34,104 +48,111 @@ public function loadConfiguration(): void
// Validates needed extension
$this->validate();

$this->loadQueryCacheConfiguration();
$this->loadHydrationCacheConfiguration();
$this->loadResultCacheConfiguration();
$this->loadMetadataCacheConfiguration();
$this->loadSecondLevelCacheConfiguration();
$definitionsHelper = new ExtensionDefinitionsHelper($this->compiler);

$this->loadQueryCacheConfiguration($definitionsHelper);
$this->loadHydrationCacheConfiguration($definitionsHelper);
$this->loadResultCacheConfiguration($definitionsHelper);
$this->loadMetadataCacheConfiguration($definitionsHelper);
$this->loadSecondLevelCacheConfiguration($definitionsHelper);
}

public function loadQueryCacheConfiguration(): void
/**
* @return Definition|string
*/
private function loadDefaultDriver(ExtensionDefinitionsHelper $definitionsHelper)
{
$builder = $this->getContainerBuilder();
$config = $this->config;
$configurationDef = $this->getConfigurationDef();

if ($config->queryCache === null && $config->defaultDriver !== null) {
$configurationDef->addSetup('setQueryCacheImpl', [
CacheBuilder::of($this)
->withDefault($config->defaultDriver)
->getDefinition('queryCache')]);
} elseif ($config->queryCache !== null) {
$builder->addDefinition($this->prefix('queryCache'))
->setFactory($config->queryCache);
if ($this->defaultDriverDef !== null) {
return $this->defaultDriverDef;
}

$configurationDef->addSetup('setQueryCacheImpl', [$this->prefix('@queryCache')]);
} else {
throw new InvalidStateException('QueryCache or defaultDriver must be provided');
if ($config->defaultDriver === null || $config->defaultDriver === []) { // Nette converts explicit null to an empty array
return $this->defaultDriverDef = '@' . Cache::class;
}

$defaultDriverName = $this->prefix('defaultCache');
$this->defaultDriverDef = $defaultDriverDef = $definitionsHelper->getDefinitionFromConfig($config->defaultDriver, $defaultDriverName);

// If service is extension specific, then disable autowiring
if ($defaultDriverDef instanceof Definition && $defaultDriverDef->getName() === $defaultDriverName) {
$defaultDriverDef->setAutowired(false);
}

return $defaultDriverDef;
}

public function loadResultCacheConfiguration(): void
/**
* @param string|mixed[]|Statement|null $config
* @return Definition|string
*/
private function loadSpecificDriver(ExtensionDefinitionsHelper $definitionsHelper, $config, string $prefix)
{
$builder = $this->getContainerBuilder();
$config = $this->config;
$configurationDef = $this->getConfigurationDef();
if ($config !== null && $config !== []) { // Nette converts explicit null to an empty array
$driverName = $this->prefix($prefix);
$driverDef = $definitionsHelper->getDefinitionFromConfig($config, $driverName);

if ($config->resultCache === null && $config->defaultDriver !== null) {
$configurationDef->addSetup('setResultCacheImpl', [
CacheBuilder::of($this)
->withDefault($config->defaultDriver)
->getDefinition('resultCache')]);
} elseif ($config->resultCache !== null) {
$builder->addDefinition($this->prefix('resultCache'))
->setFactory($config->resultCache);
// If service is extension specific, then disable autowiring
if ($driverDef instanceof Definition && $driverDef->getName() === $driverName) {
$driverDef->setAutowired(false);
}

$configurationDef->addSetup('setResultCacheImpl', [$this->prefix('@hydrationCache')]);
} else {
throw new InvalidStateException('ResultCache or defaultDriver must be provided');
return $driverDef;
}

return $this->loadDefaultDriver($definitionsHelper);
}

public function loadHydrationCacheConfiguration(): void
private function loadQueryCacheConfiguration(ExtensionDefinitionsHelper $definitionsHelper): void
{
$builder = $this->getContainerBuilder();
$config = $this->config;
$configurationDef = $this->getConfigurationDef();

if ($config->hydrationCache === null && $config->defaultDriver !== null) {
$configurationDef->addSetup('setHydrationCacheImpl', [
CacheBuilder::of($this)
->withDefault($config->defaultDriver)
->getDefinition('hydrationCache')]);
} elseif ($config->hydrationCache !== null) {
$builder->addDefinition($this->prefix('hydrationCache'))
->setFactory($config->hydrationCache);
$configurationDef->addSetup('setQueryCacheImpl', [
$this->loadSpecificDriver($definitionsHelper, $config->queryCache, 'queryCache'),
]);
}

private function loadResultCacheConfiguration(ExtensionDefinitionsHelper $definitionsHelper): void
{
$config = $this->config;
$configurationDef = $this->getConfigurationDef();

$configurationDef->addSetup('setHydrationCacheImpl', [$this->prefix('@hydrationCache')]);
} else {
throw new InvalidStateException('HydrationCache or defaultDriver must be provided');
}
$configurationDef->addSetup('setResultCacheImpl', [
$this->loadSpecificDriver($definitionsHelper, $config->resultCache, 'resultCache'),
]);
}

public function loadMetadataCacheConfiguration(): void
private function loadHydrationCacheConfiguration(ExtensionDefinitionsHelper $definitionsHelper): void
{
$builder = $this->getContainerBuilder();
$config = $this->config;
$configurationDef = $this->getConfigurationDef();

if ($config->metadataCache === null && $config->defaultDriver !== null) {
$configurationDef->addSetup('setMetadataCacheImpl', [
CacheBuilder::of($this)
->withDefault($config->defaultDriver)
->getDefinition('metadataCache')]);
} elseif ($config->metadataCache !== null) {
$builder->addDefinition($this->prefix('metadataCache'))
->setFactory($config->metadataCache);
$configurationDef->addSetup('setHydrationCacheImpl', [
$this->loadSpecificDriver($definitionsHelper, $config->hydrationCache, 'hydrationCache'),
]);
}

$configurationDef->addSetup('setMetadataCacheImpl', [$this->prefix('@metadataCache')]);
} else {
throw new InvalidStateException('MetadataCache or defaultDriver must be provided');
}
private function loadMetadataCacheConfiguration(ExtensionDefinitionsHelper $definitionsHelper): void
{
$config = $this->config;
$configurationDef = $this->getConfigurationDef();

$configurationDef->addSetup('setMetadataCacheImpl', [
$this->loadSpecificDriver($definitionsHelper, $config->metadataCache, 'metadataCache'),
]);
}

public function loadSecondLevelCacheConfiguration(): void
private function loadSecondLevelCacheConfiguration(ExtensionDefinitionsHelper $definitionsHelper): void
{
$builder = $this->getContainerBuilder();
$config = $this->config;
$configurationDef = $this->getConfigurationDef();

if ($config->secondLevelCache === null && $config->defaultDriver !== null) {
if ($config->secondLevelCache !== null) {
$cacheConfigurationDef = $definitionsHelper->getDefinitionFromConfig($config->secondLevelCache, $this->prefix('cacheConfiguration'));
} else {
$regionsDef = $builder->addDefinition($this->prefix('regions'))
->setFactory(RegionsConfiguration::class)
->setAutowired(false);
@@ -140,23 +161,20 @@ public function loadSecondLevelCacheConfiguration(): void
->setFactory(DefaultCacheFactory::class)
->setArguments([
$regionsDef,
CacheBuilder::of($this)
->withDefault($config->defaultDriver)
->getDefinition('secondLevelCache'),
$this->loadSpecificDriver($definitionsHelper, null, 'secondLevelCache'),
])
->setAutowired(false);

$cacheConfigurationDef = $builder->addDefinition($this->prefix('cacheConfiguration'))
->setFactory(CacheConfiguration::class)
->addSetup('setCacheFactory', [$cacheFactoryDef])
->setAutowired(false);

$configurationDef->addSetup('setSecondLevelCacheEnabled', [true]);
$configurationDef->addSetup('setSecondLevelCacheConfiguration', [$cacheConfigurationDef]);
} elseif ($config->secondLevelCache !== null) {
$configurationDef->addSetup('setSecondLevelCacheEnabled', [true]);
$configurationDef->addSetup('setSecondLevelCacheConfiguration', [$config->secondLevelCache]);
}

$configurationDef->addSetup('setSecondLevelCacheEnabled', [
true,
]);
$configurationDef->addSetup('setSecondLevelCacheConfiguration', [$cacheConfigurationDef]);
}

}

0 comments on commit 8f0bf73

Please sign in to comment.
You can’t perform that action at this time.