1
0
mirror of synced 2024-12-05 03:06:05 +03:00

Region cache clear commands

This commit is contained in:
fabios 2013-10-23 15:46:45 -04:00
parent fb98277783
commit 71903c28a8
14 changed files with 792 additions and 4 deletions

View File

@ -72,7 +72,7 @@ class DefaultRegion implements Region
} }
/** /**
* @return \Doctrine\Common\Cache\Cache * @return \Doctrine\Common\Cache\CacheProvider
*/ */
public function getCache() public function getCache()
{ {

View File

@ -0,0 +1,134 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Cache\Region\DefaultRegion;
use Doctrine\ORM\Cache;
/**
* Command to clear a collection cache region.
*
* @since 2.5
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*/
class CollectionRegionCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('orm:clear-cache:region:collection')
->setDescription('Clear a second-level cache collection region.')
->addArgument('owner-class', InputArgument::OPTIONAL, 'The owner entity name.')
->addArgument('association', InputArgument::OPTIONAL, 'The association collection name.')
->addArgument('owner-id', InputArgument::OPTIONAL, 'The owner identifier.')
->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all entity regions will be deleted/invalidated.')
->addOption('flush', null, InputOption::VALUE_NONE,'If defined, all cache entries will be flushed.');
$this->setHelp(<<<EOT
The <info>%command.name%</info> command is meant to clear a second-level cache collection regions for an associated Entity Manager.
It is possible to delete/invalidate all collection region, a specific collection region or flushes the cache provider.
The execution type differ on how you execute the command.
If you want to invalidate all entries for an collection region this command would do the work:
<info>%command.name% 'Entities\MyEntity' 'collectionName'</info>
To invalidate a specific entry you should use :
<info>%command.name% 'Entities\MyEntity' 'collectionName' 1</info>
If you want to invalidate all entries for the all collection regions:
<info>%command.name% --all</info>
Alternatively, if you want to flush the configured cache provider for an collection region use this command:
<info>%command.name% 'Entities\MyEntity' 'collectionName' --flush</info>
Finally, be aware that if <info>--flush</info> option is passed,
not all cache providers are able to flush entries, because of a limitation of its execution nature.
EOT
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$em = $this->getHelper('em')->getEntityManager();
$ownerClass = $input->getArgument('owner-class');
$assoc = $input->getArgument('association');
$ownerId = $input->getArgument('owner-id');
$cache = $em->getCache();
if ( ! $cache instanceof Cache) {
throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.');
}
if ( (! $ownerClass || ! $assoc) && ! $input->getOption('all')) {
throw new \InvalidArgumentException('Missing arguments "--owner-class" "--association"');
}
if ($input->getOption('flush')) {
$collectionRegion = $cache->getCollectionCacheRegion($ownerClass, $assoc);
if ( ! $collectionRegion instanceof DefaultRegion) {
throw new \InvalidArgumentException(sprintf(
'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".',
is_object($collectionRegion) ? get_class($collectionRegion) : gettype($collectionRegion)
));
}
$collectionRegion->getCache()->flushAll();
$output->writeln(sprintf('Flushing cache provider configured for <info>"%s#%s"</info>', $ownerClass, $assoc));
return;
}
if ($input->getOption('all')) {
$output->writeln('Clearing <info>all</info> second-level cache collection regions');
$cache->evictEntityRegions();
return;
}
if ($ownerId) {
$output->writeln(sprintf('Clearing second-level cache entry for collection <info>"%s#%s"</info> owner entity identified by <info>"%s"</info>', $ownerClass, $assoc, $ownerId));
$cache->evictCollection($ownerClass, $assoc, $ownerId);
return;
}
$output->writeln(sprintf('Clearing second-level cache for collection <info>"%s#%s"</info>', $ownerClass, $assoc));
$cache->evictCollectionRegion($ownerClass, $assoc);
}
}

View File

@ -0,0 +1,132 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Cache\Region\DefaultRegion;
use Doctrine\ORM\Cache;
/**
* Command to clear a entity cache region.
*
* @since 2.5
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*/
class EntityRegionCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('orm:clear-cache:region:entity')
->setDescription('Clear a second-level cache entity region.')
->addArgument('entity-class', InputArgument::OPTIONAL, 'The entity name.')
->addArgument('entity-id', InputArgument::OPTIONAL, 'The entity identifier.')
->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all entity regions will be deleted/invalidated.')
->addOption('flush', null, InputOption::VALUE_NONE,'If defined, all cache entries will be flushed.');
$this->setHelp(<<<EOT
The <info>%command.name%</info> command is meant to clear a second-level cache entity region for an associated Entity Manager.
It is possible to delete/invalidate all entity region, a specific entity region or flushes the cache provider.
The execution type differ on how you execute the command.
If you want to invalidate all entries for an entity region this command would do the work:
<info>%command.name% 'Entities\MyEntity'</info>
To invalidate a specific entry you should use :
<info>%command.name% 'Entities\MyEntity' 1</info>
If you want to invalidate all entries for the all entity regions:
<info>%command.name% --all</info>
Alternatively, if you want to flush the configured cache provider for an entity region use this command:
<info>%command.name% 'Entities\MyEntity' --flush</info>
Finally, be aware that if <info>--flush</info> option is passed,
not all cache providers are able to flush entries, because of a limitation of its execution nature.
EOT
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$em = $this->getHelper('em')->getEntityManager();
$entityClass = $input->getArgument('entity-class');
$entityId = $input->getArgument('entity-id');
$cache = $em->getCache();
if ( ! $cache instanceof Cache) {
throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.');
}
if ( ! $entityClass && ! $input->getOption('all')) {
throw new \InvalidArgumentException('Invalid argument "--entity-class"');
}
if ($input->getOption('flush')) {
$entityRegion = $cache->getEntityCacheRegion($entityClass);
if ( ! $entityRegion instanceof DefaultRegion) {
throw new \InvalidArgumentException(sprintf(
'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".',
is_object($entityRegion) ? get_class($entityRegion) : gettype($entityRegion)
));
}
$entityRegion->getCache()->flushAll();
$output->writeln(sprintf('Flushing cache provider configured for entity named <info>"%s"</info>', $entityClass));
return;
}
if ($input->getOption('all')) {
$output->writeln('Clearing <info>all</info> second-level cache entity regions');
$cache->evictEntityRegions();
return;
}
if ($entityId) {
$output->writeln(sprintf('Clearing second-level cache entry for entity <info>"%s"</info> identified by <info>"%s"</info>', $entityClass, $entityId));
$cache->evictEntity($entityClass, $entityId);
return;
}
$output->writeln(sprintf('Clearing second-level cache for entity <info>"%s"</info>', $entityClass));
$cache->evictEntityRegion($entityClass);
}
}

View File

@ -0,0 +1,124 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Cache\Region\DefaultRegion;
use Doctrine\ORM\Cache;
/**
* Command to clear a query cache region.
*
* @since 2.5
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*/
class QueryRegionCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('orm:clear-cache:region:query')
->setDescription('Clear a second-level cache query region.')
->addArgument('region-name', InputArgument::OPTIONAL, 'The query region to clear.')
->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all query regions will be deleted/invalidated.')
->addOption('flush', null, InputOption::VALUE_NONE,'If defined, all cache entries will be flushed.');
$this->setHelp(<<<EOT
The <info>%command.name%</info> command is meant to clear a second-level cache query region for an associated Entity Manager.
It is possible to delete/invalidate all query region, a specific query region or flushes the cache provider.
The execution type differ on how you execute the command.
If you want to invalidate all entries for the default query region this command would do the work:
<info>%command.name%</info>
To invalidate entries for a specific query region you should use :
<info>%command.name% my_region_name</info>
If you want to invalidate all entries for the all query region:
<info>%command.name% --all</info>
Alternatively, if you want to flush the configured cache provider use this command:
<info>%command.name% my_region_name --flush</info>
Finally, be aware that if <info>--flush</info> option is passed,
not all cache providers are able to flush entries, because of a limitation of its execution nature.
EOT
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$em = $this->getHelper('em')->getEntityManager();
$name = $input->getArgument('region-name');
$cache = $em->getCache();
if ($name === null) {
$name = Cache::DEFAULT_QUERY_REGION_NAME;
}
if ( ! $cache instanceof Cache) {
throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.');
}
if ($input->getOption('flush')) {
$queryCache = $cache->getQueryCache($name);
$queryRegion = $queryCache->getRegion();
if ( ! $queryRegion instanceof DefaultRegion) {
throw new \InvalidArgumentException(sprintf(
'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".',
is_object($queryRegion) ? get_class($queryRegion) : gettype($queryRegion)
));
}
$queryRegion->getCache()->flushAll();
$output->writeln(sprintf('Flushing cache provider configured for second-level cache query region named <info>"%s"</info>', $name));
return;
}
if ($input->getOption('all')) {
$output->writeln('Clearing <info>all</info> second-level cache query regions');
$cache->evictQueryRegions();
return;
}
$output->writeln(sprintf('Clearing second-level cache query region named <info>"%s"</info>', $name));
$cache->evictQueryRegion($name);
}
}

View File

@ -4,6 +4,9 @@ namespace Doctrine\Tests\Mocks;
use Doctrine\ORM\Cache\CacheEntry; use Doctrine\ORM\Cache\CacheEntry;
/**
* Cache entry mock
*/
class CacheEntryMock extends \ArrayObject implements CacheEntry class CacheEntryMock extends \ArrayObject implements CacheEntry
{ {

View File

@ -4,8 +4,16 @@ namespace Doctrine\Tests\Mocks;
use Doctrine\ORM\Cache\CacheKey; use Doctrine\ORM\Cache\CacheKey;
/**
* Cache key mock
*
* Used to store/retrieve entries from a cache region
*/
class CacheKeyMock extends CacheKey class CacheKeyMock extends CacheKey
{ {
/**
* @param string $hash The string hash that represend this cache key
*/
function __construct($hash) function __construct($hash)
{ {
$this->hash = $hash; $this->hash = $hash;

View File

@ -7,18 +7,35 @@ use Doctrine\ORM\Cache\CacheKey;
use Doctrine\ORM\Cache\Lock; use Doctrine\ORM\Cache\Lock;
use Doctrine\ORM\Cache\Region; use Doctrine\ORM\Cache\Region;
/**
* Cache region mock
*/
class CacheRegionMock implements Region class CacheRegionMock implements Region
{ {
public $calls = array(); public $calls = array();
public $returns = array(); public $returns = array();
public $name; public $name;
/**
* Queue a return value for a specific method invocation
*
* @param string $method
* @param mixed $value
*/
public function addReturn($method, $value) public function addReturn($method, $value)
{ {
$this->returns[$method][] = $value; $this->returns[$method][] = $value;
} }
public function getReturn($method, $default) /**
* Dequeue a value for a specific method invocation
*
* @param string $method
* @param mixed $default
*
* @return mixed
*/
private function getReturn($method, $default)
{ {
if (isset($this->returns[$method]) && ! empty($this->returns[$method])) { if (isset($this->returns[$method]) && ! empty($this->returns[$method])) {
return array_shift($this->returns[$method]); return array_shift($this->returns[$method]);
@ -27,6 +44,9 @@ class CacheRegionMock implements Region
return $default; return $default;
} }
/**
* {@inheritdoc}
*/
public function getName() public function getName()
{ {
$this->calls[__FUNCTION__][] = array(); $this->calls[__FUNCTION__][] = array();
@ -34,6 +54,9 @@ class CacheRegionMock implements Region
return $this->name; return $this->name;
} }
/**
* {@inheritdoc}
*/
public function contains(CacheKey $key) public function contains(CacheKey $key)
{ {
$this->calls[__FUNCTION__][] = array('key' => $key); $this->calls[__FUNCTION__][] = array('key' => $key);
@ -41,6 +64,9 @@ class CacheRegionMock implements Region
return $this->getReturn(__FUNCTION__, false); return $this->getReturn(__FUNCTION__, false);
} }
/**
* {@inheritdoc}
*/
public function evict(CacheKey $key) public function evict(CacheKey $key)
{ {
$this->calls[__FUNCTION__][] = array('key' => $key); $this->calls[__FUNCTION__][] = array('key' => $key);
@ -48,6 +74,9 @@ class CacheRegionMock implements Region
return $this->getReturn(__FUNCTION__, true); return $this->getReturn(__FUNCTION__, true);
} }
/**
* {@inheritdoc}
*/
public function evictAll() public function evictAll()
{ {
$this->calls[__FUNCTION__][] = array(); $this->calls[__FUNCTION__][] = array();
@ -55,6 +84,9 @@ class CacheRegionMock implements Region
return $this->getReturn(__FUNCTION__, true); return $this->getReturn(__FUNCTION__, true);
} }
/**
* {@inheritdoc}
*/
public function get(CacheKey $key) public function get(CacheKey $key)
{ {
$this->calls[__FUNCTION__][] = array('key' => $key); $this->calls[__FUNCTION__][] = array('key' => $key);
@ -62,6 +94,9 @@ class CacheRegionMock implements Region
return $this->getReturn(__FUNCTION__, null); return $this->getReturn(__FUNCTION__, null);
} }
/**
* {@inheritdoc}
*/
public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null) public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null)
{ {
$this->calls[__FUNCTION__][] = array('key' => $key, 'entry' => $entry); $this->calls[__FUNCTION__][] = array('key' => $key, 'entry' => $entry);
@ -69,6 +104,9 @@ class CacheRegionMock implements Region
return $this->getReturn(__FUNCTION__, true); return $this->getReturn(__FUNCTION__, true);
} }
/**
* {@inheritdoc}
*/
public function clear() public function clear()
{ {
$this->calls = array(); $this->calls = array();

View File

@ -10,6 +10,11 @@ use Doctrine\ORM\Cache\CacheKey;
use Doctrine\ORM\Cache\Region; use Doctrine\ORM\Cache\Region;
use Doctrine\ORM\Cache\Lock; use Doctrine\ORM\Cache\Lock;
/**
* Concurrent region mock
*
* Used to mock a ConcurrentRegion
*/
class ConcurrentRegionMock implements ConcurrentRegion class ConcurrentRegionMock implements ConcurrentRegion
{ {
public $calls = array(); public $calls = array();
@ -21,11 +26,22 @@ class ConcurrentRegionMock implements ConcurrentRegion
*/ */
private $region; private $region;
/**
* @param \Doctrine\ORM\Cache\Region $region
*/
public function __construct(Region $region) public function __construct(Region $region)
{ {
$this->region = $region; $this->region = $region;
} }
/**
* Dequeue an exception for a specific method invocation
*
* @param string $method
* @param mixed $default
*
* @return mixed
*/
private function throwException($method) private function throwException($method)
{ {
if (isset($this->exceptions[$method]) && ! empty($this->exceptions[$method])) { if (isset($this->exceptions[$method]) && ! empty($this->exceptions[$method])) {
@ -37,16 +53,31 @@ class ConcurrentRegionMock implements ConcurrentRegion
} }
} }
/**
* Queue an exception for the next method invocation
*
* @param string $method
* @param \Exception $e
*/
public function addException($method, \Exception $e) public function addException($method, \Exception $e)
{ {
$this->exceptions[$method][] = $e; $this->exceptions[$method][] = $e;
} }
/**
* Locks a specific cache entry
*
* @param \Doctrine\ORM\Cache\CacheKey $key
* @param \Doctrine\ORM\Cache\Lock $lock
*/
public function setLock(CacheKey $key, Lock $lock) public function setLock(CacheKey $key, Lock $lock)
{ {
$this->locks[$key->hash] = $lock; $this->locks[$key->hash] = $lock;
} }
/**
* {@inheritdoc}
*/
public function contains(CacheKey $key) public function contains(CacheKey $key)
{ {
$this->calls[__FUNCTION__][] = array('key' => $key); $this->calls[__FUNCTION__][] = array('key' => $key);
@ -60,6 +91,9 @@ class ConcurrentRegionMock implements ConcurrentRegion
return $this->region->contains($key); return $this->region->contains($key);
} }
/**
* {@inheritdoc}
*/
public function evict(CacheKey $key) public function evict(CacheKey $key)
{ {
$this->calls[__FUNCTION__][] = array('key' => $key); $this->calls[__FUNCTION__][] = array('key' => $key);
@ -69,6 +103,9 @@ class ConcurrentRegionMock implements ConcurrentRegion
return $this->region->evict($key); return $this->region->evict($key);
} }
/**
* {@inheritdoc}
*/
public function evictAll() public function evictAll()
{ {
$this->calls[__FUNCTION__][] = array(); $this->calls[__FUNCTION__][] = array();
@ -78,6 +115,9 @@ class ConcurrentRegionMock implements ConcurrentRegion
return $this->region->evictAll(); return $this->region->evictAll();
} }
/**
* {@inheritdoc}
*/
public function get(CacheKey $key) public function get(CacheKey $key)
{ {
$this->calls[__FUNCTION__][] = array('key' => $key); $this->calls[__FUNCTION__][] = array('key' => $key);
@ -91,6 +131,9 @@ class ConcurrentRegionMock implements ConcurrentRegion
return $this->region->get($key); return $this->region->get($key);
} }
/**
* {@inheritdoc}
*/
public function getName() public function getName()
{ {
$this->calls[__FUNCTION__][] = array(); $this->calls[__FUNCTION__][] = array();
@ -100,6 +143,9 @@ class ConcurrentRegionMock implements ConcurrentRegion
return $this->region->getName(); return $this->region->getName();
} }
/**
* {@inheritdoc}
*/
public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null) public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null)
{ {
$this->calls[__FUNCTION__][] = array('key' => $key, 'entry' => $entry); $this->calls[__FUNCTION__][] = array('key' => $key, 'entry' => $entry);
@ -118,6 +164,9 @@ class ConcurrentRegionMock implements ConcurrentRegion
return $this->region->put($key, $entry); return $this->region->put($key, $entry);
} }
/**
* {@inheritdoc}
*/
public function lock(CacheKey $key) public function lock(CacheKey $key)
{ {
$this->calls[__FUNCTION__][] = array('key' => $key); $this->calls[__FUNCTION__][] = array('key' => $key);
@ -131,6 +180,9 @@ class ConcurrentRegionMock implements ConcurrentRegion
return $this->locks[$key->hash] = Lock::createLockRead(); return $this->locks[$key->hash] = Lock::createLockRead();
} }
/**
* {@inheritdoc}
*/
public function unlock(CacheKey $key, Lock $lock) public function unlock(CacheKey $key, Lock $lock)
{ {
$this->calls[__FUNCTION__][] = array('key' => $key, 'lock' => $lock); $this->calls[__FUNCTION__][] = array('key' => $key, 'lock' => $lock);

View File

@ -5,6 +5,11 @@ namespace Doctrine\Tests\Mocks;
use Doctrine\ORM\Cache\TimestampRegion; use Doctrine\ORM\Cache\TimestampRegion;
use Doctrine\ORM\Cache\CacheKey; use Doctrine\ORM\Cache\CacheKey;
/**
* Timestamp region mock
*
* Used to mock a TimestampRegion
*/
class TimestampRegionMock extends CacheRegionMock implements TimestampRegion class TimestampRegionMock extends CacheRegionMock implements TimestampRegion
{ {
public function update(CacheKey $key) public function update(CacheKey $key)

View File

@ -0,0 +1,94 @@
<?php
namespace Doctrine\Tests\ORM\Tools\Console\Command;
use Doctrine\ORM\Tools\Console\Command\ClearCache\CollectionRegionCommand;
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Application;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* @group DDC-2183
*/
class ClearCacheCollectionRegionCommandTest extends OrmFunctionalTestCase
{
/**
* @var \Symfony\Component\Console\Application
*/
private $application;
/**
* @var \Doctrine\ORM\Tools\Console\Command\ClearCache\CollectionRegionCommand
*/
private $command;
protected function setUp()
{
$this->enableSecondLevelCache();
parent::setUp();
$this->application = new Application();
$this->command = new CollectionRegionCommand();
$this->application->setHelperSet(new HelperSet(array(
'em' => new EntityManagerHelper($this->_em)
)));
$this->application->add($this->command);
}
public function testClearAllRegion()
{
$command = $this->application->find('orm:clear-cache:region:collection');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'--all' => true,
));
$this->assertEquals('Clearing all second-level cache collection regions' . PHP_EOL, $tester->getDisplay());
}
public function testClearByOwnerEntityClassName()
{
$command = $this->application->find('orm:clear-cache:region:collection');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'owner-class' => 'Doctrine\Tests\Models\Cache\State',
'association' => 'cities',
));
$this->assertEquals('Clearing second-level cache for collection "Doctrine\Tests\Models\Cache\State#cities"' . PHP_EOL, $tester->getDisplay());
}
public function testClearCacheEntryName()
{
$command = $this->application->find('orm:clear-cache:region:collection');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'owner-class' => 'Doctrine\Tests\Models\Cache\State',
'association' => 'cities',
'owner-id' => 1,
));
$this->assertEquals('Clearing second-level cache entry for collection "Doctrine\Tests\Models\Cache\State#cities" owner entity identified by "1"' . PHP_EOL, $tester->getDisplay());
}
public function testFlushRegionName()
{
$command = $this->application->find('orm:clear-cache:region:collection');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'owner-class' => 'Doctrine\Tests\Models\Cache\State',
'association' => 'cities',
'--flush' => true,
));
$this->assertEquals('Flushing cache provider configured for "Doctrine\Tests\Models\Cache\State#cities"' . PHP_EOL, $tester->getDisplay());
}
}

View File

@ -0,0 +1,91 @@
<?php
namespace Doctrine\Tests\ORM\Tools\Console\Command;
use Doctrine\ORM\Tools\Console\Command\ClearCache\EntityRegionCommand;
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Application;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* @group DDC-2183
*/
class ClearCacheEntityRegionCommandTest extends OrmFunctionalTestCase
{
/**
* @var \Symfony\Component\Console\Application
*/
private $application;
/**
* @var \Doctrine\ORM\Tools\Console\Command\ClearCache\EntityRegionCommand
*/
private $command;
protected function setUp()
{
$this->enableSecondLevelCache();
parent::setUp();
$this->application = new Application();
$this->command = new EntityRegionCommand();
$this->application->setHelperSet(new HelperSet(array(
'em' => new EntityManagerHelper($this->_em)
)));
$this->application->add($this->command);
}
public function testClearAllRegion()
{
$command = $this->application->find('orm:clear-cache:region:entity');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'--all' => true,
));
$this->assertEquals('Clearing all second-level cache entity regions' . PHP_EOL, $tester->getDisplay());
}
public function testClearByEntityClassName()
{
$command = $this->application->find('orm:clear-cache:region:entity');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'entity-class' => 'Doctrine\Tests\Models\Cache\Country',
));
$this->assertEquals('Clearing second-level cache for entity "Doctrine\Tests\Models\Cache\Country"' . PHP_EOL, $tester->getDisplay());
}
public function testClearCacheEntryName()
{
$command = $this->application->find('orm:clear-cache:region:entity');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'entity-class' => 'Doctrine\Tests\Models\Cache\Country',
'entity-id' => 1,
));
$this->assertEquals('Clearing second-level cache entry for entity "Doctrine\Tests\Models\Cache\Country" identified by "1"' . PHP_EOL, $tester->getDisplay());
}
public function testFlushRegionName()
{
$command = $this->application->find('orm:clear-cache:region:entity');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'entity-class' => 'Doctrine\Tests\Models\Cache\Country',
'--flush' => true,
));
$this->assertEquals('Flushing cache provider configured for entity named "Doctrine\Tests\Models\Cache\Country"' . PHP_EOL, $tester->getDisplay());
}
}

View File

@ -0,0 +1,90 @@
<?php
namespace Doctrine\Tests\ORM\Tools\Console\Command;
use Doctrine\ORM\Tools\Console\Command\ClearCache\QueryRegionCommand;
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Application;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* @group DDC-2183
*/
class ClearCacheQueryRegionCommandTest extends OrmFunctionalTestCase
{
/**
* @var \Symfony\Component\Console\Application
*/
private $application;
/**
* @var \Doctrine\ORM\Tools\Console\Command\ClearCache\QueryRegionCommand
*/
private $command;
protected function setUp()
{
$this->enableSecondLevelCache();
parent::setUp();
$this->application = new Application();
$this->command = new QueryRegionCommand();
$this->application->setHelperSet(new HelperSet(array(
'em' => new EntityManagerHelper($this->_em)
)));
$this->application->add($this->command);
}
public function testClearAllRegion()
{
$command = $this->application->find('orm:clear-cache:region:query');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'--all' => true,
));
$this->assertEquals('Clearing all second-level cache query regions' . PHP_EOL, $tester->getDisplay());
}
public function testClearDefaultRegionName()
{
$command = $this->application->find('orm:clear-cache:region:query');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'region-name' => null,
));
$this->assertEquals('Clearing second-level cache query region named "query_cache_region"' . PHP_EOL, $tester->getDisplay());
}
public function testClearByRegionName()
{
$command = $this->application->find('orm:clear-cache:region:query');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'region-name' => 'my_region',
));
$this->assertEquals('Clearing second-level cache query region named "my_region"' . PHP_EOL, $tester->getDisplay());
}
public function testFlushRegionName()
{
$command = $this->application->find('orm:clear-cache:region:query');
$tester = new CommandTester($command);
$tester->execute(array(
'command' => $command->getName(),
'region-name' => 'my_region',
'--flush' => true,
));
$this->assertEquals('Flushing cache provider configured for second-level cache query region named "my_region"' . PHP_EOL, $tester->getDisplay());
}
}

View File

@ -38,4 +38,18 @@ $connectionOptions = array(
'path' => 'database.sqlite' 'path' => 'database.sqlite'
); );
// Enable second-level cache
$cacheConfig = new \Doctrine\ORM\Cache\CacheConfiguration();
$cacheDriver = $debug ? new Cache\ArrayCache : new Cache\ApcCache;
$cacheLogger = new \Doctrine\ORM\Cache\Logging\StatisticsCacheLogger();
$factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($cacheConfig->getRegionsConfiguration(), $cacheDriver);
if ($debug) {
$cacheConfig->setCacheLogger($cacheLogger);
}
$cacheConfig->setCacheFactory($factory);
$config->setSecondLevelCacheEnabled(true);
$config->setSecondLevelCacheConfiguration($cacheConfig);
return EntityManager::create($connectionOptions, $config); return EntityManager::create($connectionOptions, $config);

View File

@ -16,6 +16,9 @@ $cli->addCommands(array(
new \Doctrine\DBAL\Tools\Console\Command\ImportCommand(), new \Doctrine\DBAL\Tools\Console\Command\ImportCommand(),
// ORM Commands // ORM Commands
new \Doctrine\ORM\Tools\Console\Command\ClearCache\QueryRegionCommand(),
new \Doctrine\ORM\Tools\Console\Command\ClearCache\EntityRegionCommand(),
new \Doctrine\ORM\Tools\Console\Command\ClearCache\CollectionRegionCommand(),
new \Doctrine\ORM\Tools\Console\Command\ClearCache\MetadataCommand(), new \Doctrine\ORM\Tools\Console\Command\ClearCache\MetadataCommand(),
new \Doctrine\ORM\Tools\Console\Command\ClearCache\ResultCommand(), new \Doctrine\ORM\Tools\Console\Command\ClearCache\ResultCommand(),
new \Doctrine\ORM\Tools\Console\Command\ClearCache\QueryCommand(), new \Doctrine\ORM\Tools\Console\Command\ClearCache\QueryCommand(),