feature #24226 [Cache] Add ResettableInterface to allow resetting any pool's local state (nicolas-grekas)

This PR was merged into the 3.4 branch.

Discussion
----------

[Cache] Add ResettableInterface to allow resetting any pool's local state

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

To allow pools to leverage #24155 so that they can be used in multi-request loops.

Commits
-------

14c91f2 [Cache] Add ResettableInterface to allow resetting any pool's local state
This commit is contained in:
Nicolas Grekas 2017-09-25 11:23:16 +02:00
commit 0c0a0525a1
33 changed files with 315 additions and 70 deletions

View File

@ -43,6 +43,7 @@ class CachePoolPass implements CompilerPassInterface
'provider',
'namespace',
'default_lifetime',
'reset',
);
foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) {
$adapter = $pool = $container->getDefinition($id);
@ -73,13 +74,19 @@ class CachePoolPass implements CompilerPassInterface
}
$i = 0;
foreach ($attributes as $attr) {
if (isset($tags[0][$attr]) && ('namespace' !== $attr || ArrayAdapter::class !== $adapter->getClass())) {
if (!isset($tags[0][$attr])) {
// no-op
} elseif ('reset' === $attr) {
if ($tags[0][$attr]) {
$pool->addTag('kernel.reset', array('method' => $tags[0][$attr]));
}
} elseif ('namespace' !== $attr || ArrayAdapter::class !== $adapter->getClass()) {
$pool->replaceArgument($i++, $tags[0][$attr]);
}
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" and "default_lifetime", found "%s".', $id, implode('", "', array_keys($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]))));
}
if (null !== $clearer) {

View File

@ -25,6 +25,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Resource\DirectoryResource;
@ -339,6 +340,8 @@ class FrameworkExtension extends Extension
->addTag('kernel.cache_warmer');
$container->registerForAutoconfiguration(EventSubscriberInterface::class)
->addTag('kernel.event_subscriber');
$container->registerForAutoconfiguration(ResettableInterface::class)
->addTag('kernel.reset', array('method' => 'reset'));
$container->registerForAutoconfiguration(PropertyListExtractorInterface::class)
->addTag('property_info.list_extractor');
$container->registerForAutoconfiguration(PropertyTypeExtractorInterface::class)

View File

@ -8,7 +8,7 @@
<defaults public="false" />
<service id="cache.app" parent="cache.adapter.filesystem" public="true">
<tag name="cache.pool" clearer="cache.app_clearer" />
<tag name="cache.pool" clearer="cache.app_clearer" reset="reset" />
</service>
<service id="cache.system" parent="cache.adapter.system" public="true">
@ -90,7 +90,7 @@
</service>
<service id="cache.adapter.memcached" class="Symfony\Component\Cache\Adapter\MemcachedAdapter" abstract="true">
<tag name="cache.pool" provider="cache.default_memcached_provider" clearer="cache.default_clearer" />
<tag name="cache.pool" provider="cache.default_memcached_provider" clearer="cache.default_clearer" reset="reset" />
<tag name="monolog.logger" channel="cache" />
<argument /> <!-- Memcached connection service -->
<argument /> <!-- namespace -->

View File

@ -17,12 +17,13 @@ use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\AbstractTrait;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface
abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface, ResettableInterface
{
use AbstractTrait;

View File

@ -14,12 +14,13 @@ namespace Symfony\Component\Cache\Adapter;
use Psr\Cache\CacheItemInterface;
use Psr\Log\LoggerAwareInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\ArrayTrait;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class ArrayAdapter implements AdapterInterface, LoggerAwareInterface
class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, ResettableInterface
{
use ArrayTrait;

View File

@ -16,6 +16,7 @@ use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
/**
* Chains several adapters together.
@ -25,7 +26,7 @@ use Symfony\Component\Cache\PruneableInterface;
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class ChainAdapter implements AdapterInterface, PruneableInterface
class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableInterface
{
private $adapters = array();
private $adapterCount;
@ -248,4 +249,16 @@ class ChainAdapter implements AdapterInterface, PruneableInterface
return $pruned;
}
/**
* {@inheritdoc}
*/
public function reset()
{
foreach ($this->adapters as $adapter) {
if ($adapter instanceof ResettableInterface) {
$adapter->reset();
}
}
}
}

View File

@ -15,6 +15,8 @@ use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\PhpArrayTrait;
/**
@ -24,7 +26,7 @@ use Symfony\Component\Cache\Traits\PhpArrayTrait;
* @author Titouan Galopin <galopintitouan@gmail.com>
* @author Nicolas Grekas <p@tchwork.com>
*/
class PhpArrayAdapter implements AdapterInterface
class PhpArrayAdapter implements AdapterInterface, PruneableInterface, ResettableInterface
{
use PhpArrayTrait;
@ -37,7 +39,7 @@ class PhpArrayAdapter implements AdapterInterface
public function __construct($file, AdapterInterface $fallbackPool)
{
$this->file = $file;
$this->fallbackPool = $fallbackPool;
$this->pool = $fallbackPool;
$this->zendDetectUnicode = ini_get('zend.detect_unicode');
$this->createCacheItem = \Closure::bind(
function ($key, $value, $isHit) {
@ -89,7 +91,7 @@ class PhpArrayAdapter implements AdapterInterface
$this->initialize();
}
if (!isset($this->values[$key])) {
return $this->fallbackPool->getItem($key);
return $this->pool->getItem($key);
}
$value = $this->values[$key];
@ -144,7 +146,7 @@ class PhpArrayAdapter implements AdapterInterface
$this->initialize();
}
return isset($this->values[$key]) || $this->fallbackPool->hasItem($key);
return isset($this->values[$key]) || $this->pool->hasItem($key);
}
/**
@ -159,7 +161,7 @@ class PhpArrayAdapter implements AdapterInterface
$this->initialize();
}
return !isset($this->values[$key]) && $this->fallbackPool->deleteItem($key);
return !isset($this->values[$key]) && $this->pool->deleteItem($key);
}
/**
@ -186,7 +188,7 @@ class PhpArrayAdapter implements AdapterInterface
}
if ($fallbackKeys) {
$deleted = $this->fallbackPool->deleteItems($fallbackKeys) && $deleted;
$deleted = $this->pool->deleteItems($fallbackKeys) && $deleted;
}
return $deleted;
@ -201,7 +203,7 @@ class PhpArrayAdapter implements AdapterInterface
$this->initialize();
}
return !isset($this->values[$item->getKey()]) && $this->fallbackPool->save($item);
return !isset($this->values[$item->getKey()]) && $this->pool->save($item);
}
/**
@ -213,7 +215,7 @@ class PhpArrayAdapter implements AdapterInterface
$this->initialize();
}
return !isset($this->values[$item->getKey()]) && $this->fallbackPool->saveDeferred($item);
return !isset($this->values[$item->getKey()]) && $this->pool->saveDeferred($item);
}
/**
@ -221,7 +223,7 @@ class PhpArrayAdapter implements AdapterInterface
*/
public function commit()
{
return $this->fallbackPool->commit();
return $this->pool->commit();
}
/**
@ -259,7 +261,7 @@ class PhpArrayAdapter implements AdapterInterface
}
if ($fallbackKeys) {
foreach ($this->fallbackPool->getItems($fallbackKeys) as $key => $item) {
foreach ($this->pool->getItems($fallbackKeys) as $key => $item) {
yield $key => $item;
}
}

View File

@ -14,13 +14,17 @@ namespace Symfony\Component\Cache\Adapter;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\ProxyTrait;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class ProxyAdapter implements AdapterInterface
class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableInterface
{
private $pool;
use ProxyTrait;
private $namespace;
private $namespaceLen;
private $createCacheItem;

View File

@ -12,13 +12,17 @@
namespace Symfony\Component\Cache\Adapter;
use Psr\SimpleCache\CacheInterface;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\ProxyTrait;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class SimpleCacheAdapter extends AbstractAdapter
class SimpleCacheAdapter extends AbstractAdapter implements PruneableInterface, ResettableInterface
{
private $pool;
use ProxyTrait;
private $miss;
public function __construct(CacheInterface $pool, $namespace = '', $defaultLifetime = 0)

View File

@ -15,26 +15,29 @@ use Psr\Cache\CacheItemInterface;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\ProxyTrait;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface
class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, ResettableInterface
{
const TAGS_PREFIX = "\0tags\0";
private $itemsAdapter;
use ProxyTrait;
private $deferred = array();
private $createCacheItem;
private $setCacheItemTags;
private $getTagsByKey;
private $invalidateTags;
private $tagsAdapter;
private $tagsPool;
public function __construct(AdapterInterface $itemsAdapter, AdapterInterface $tagsAdapter = null)
public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null)
{
$this->itemsAdapter = $itemsAdapter;
$this->tagsAdapter = $tagsAdapter ?: $itemsAdapter;
$this->pool = $itemsPool;
$this->tags = $tagsPool ?: $itemsPool;
$this->createCacheItem = \Closure::bind(
function ($key, $value, CacheItem $protoItem) {
$item = new CacheItem();
@ -110,7 +113,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface
}
$f = $this->invalidateTags;
return $f($this->tagsAdapter, $tags);
return $f($this->tags, $tags);
}
/**
@ -121,10 +124,10 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface
if ($this->deferred) {
$this->commit();
}
if (!$this->itemsAdapter->hasItem($key)) {
if (!$this->pool->hasItem($key)) {
return false;
}
if (!$itemTags = $this->itemsAdapter->getItem(static::TAGS_PREFIX.$key)->get()) {
if (!$itemTags = $this->pool->getItem(static::TAGS_PREFIX.$key)->get()) {
return true;
}
@ -165,9 +168,9 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface
}
try {
$items = $this->itemsAdapter->getItems($tagKeys + $keys);
$items = $this->pool->getItems($tagKeys + $keys);
} catch (InvalidArgumentException $e) {
$this->itemsAdapter->getItems($keys); // Should throw an exception
$this->pool->getItems($keys); // Should throw an exception
throw $e;
}
@ -182,7 +185,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface
{
$this->deferred = array();
return $this->itemsAdapter->clear();
return $this->pool->clear();
}
/**
@ -204,7 +207,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface
}
}
return $this->itemsAdapter->deleteItems($keys);
return $this->pool->deleteItems($keys);
}
/**
@ -243,7 +246,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface
if ($this->deferred) {
$items = $this->deferred;
foreach ($items as $key => $item) {
if (!$this->itemsAdapter->saveDeferred($item)) {
if (!$this->pool->saveDeferred($item)) {
unset($this->deferred[$key]);
$ok = false;
}
@ -257,17 +260,17 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface
foreach ($tagsByKey as $key => $tags) {
if ($tags) {
$this->itemsAdapter->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
$this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
} else {
$deletedTags[] = static::TAGS_PREFIX.$key;
}
}
if ($deletedTags) {
$this->itemsAdapter->deleteItems($deletedTags);
$this->pool->deleteItems($deletedTags);
}
}
return $this->itemsAdapter->commit() && $ok;
return $this->pool->commit() && $ok;
}
public function __destruct()
@ -328,23 +331,11 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface
$tagVersions[$tag] = $tag.static::TAGS_PREFIX;
$tags[$tag.static::TAGS_PREFIX] = $tag;
}
foreach ($this->tagsAdapter->getItems($tagVersions) as $tag => $version) {
foreach ($this->tags->getItems($tagVersions) as $tag => $version) {
$tagVersions[$tags[$tag]] = $version->get() ?: 0;
}
}
return $tagVersions;
}
/**
* {@inheritdoc}
*/
public function prune()
{
if ($this->itemsAdapter instanceof PruneableInterface) {
return $this->itemsAdapter->prune();
}
return false;
}
}

View File

@ -12,6 +12,8 @@
namespace Symfony\Component\Cache\Adapter;
use Psr\Cache\CacheItemInterface;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
/**
* An adapter that collects data about all cache calls.
@ -20,7 +22,7 @@ use Psr\Cache\CacheItemInterface;
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
* @author Nicolas Grekas <p@tchwork.com>
*/
class TraceableAdapter implements AdapterInterface
class TraceableAdapter implements AdapterInterface, PruneableInterface, ResettableInterface
{
protected $pool;
private $calls = array();
@ -168,6 +170,38 @@ class TraceableAdapter implements AdapterInterface
}
}
/**
* {@inheritdoc}
*/
public function prune()
{
if (!$this->pool instanceof PruneableInterface) {
return false;
}
$event = $this->start(__FUNCTION__);
try {
return $event->result = $this->pool->prune();
} finally {
$event->end = microtime(true);
}
}
/**
* {@inheritdoc}
*/
public function reset()
{
if (!$this->pool instanceof ResettableInterface) {
return;
}
$event = $this->start(__FUNCTION__);
try {
$this->pool->reset();
} finally {
$event->end = microtime(true);
}
}
public function getCalls()
{
try {

View File

@ -17,7 +17,7 @@ use Psr\Cache\CacheItemPoolInterface;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class DoctrineProvider extends CacheProvider
class DoctrineProvider extends CacheProvider implements PruneableInterface, ResettableInterface
{
private $pool;
@ -26,6 +26,25 @@ class DoctrineProvider extends CacheProvider
$this->pool = $pool;
}
/**
* {@inheritdoc}
*/
public function prune()
{
return $this->pool instanceof PruneableInterface && $this->pool->prune();
}
/**
* {@inheritdoc}
*/
public function reset()
{
if ($this->pool instanceof ResettableInterface) {
$this->pool->reset();
}
$this->setNamespace($this->getNamespace());
}
/**
* {@inheritdoc}
*/

View File

@ -0,0 +1,20 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Cache;
/**
* Resets a pool's local state.
*/
interface ResettableInterface
{
public function reset();
}

View File

@ -16,11 +16,12 @@ use Psr\SimpleCache\CacheInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\Traits\AbstractTrait;
use Symfony\Component\Cache\ResettableInterface;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
abstract class AbstractCache implements CacheInterface, LoggerAwareInterface
abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, ResettableInterface
{
use AbstractTrait {
deleteItems as private;

View File

@ -15,12 +15,13 @@ use Psr\Log\LoggerAwareInterface;
use Psr\SimpleCache\CacheInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\ArrayTrait;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class ArrayCache implements CacheInterface, LoggerAwareInterface
class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInterface
{
use ArrayTrait {
ArrayTrait::deleteItem as delete;

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Cache\Simple;
use Psr\SimpleCache\CacheInterface;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
/**
* Chains several caches together.
@ -23,7 +24,7 @@ use Symfony\Component\Cache\PruneableInterface;
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class ChainCache implements CacheInterface, PruneableInterface
class ChainCache implements CacheInterface, PruneableInterface, ResettableInterface
{
private $miss;
private $caches = array();
@ -236,4 +237,16 @@ class ChainCache implements CacheInterface, PruneableInterface
return $pruned;
}
/**
* {@inheritdoc}
*/
public function reset()
{
foreach ($this->caches as $cache) {
if ($cache instanceof ResettableInterface) {
$cache->reset();
}
}
}
}

View File

@ -14,6 +14,8 @@ namespace Symfony\Component\Cache\Simple;
use Psr\SimpleCache\CacheInterface;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\Traits\PhpArrayTrait;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
/**
* Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0.
@ -22,7 +24,7 @@ use Symfony\Component\Cache\Traits\PhpArrayTrait;
* @author Titouan Galopin <galopintitouan@gmail.com>
* @author Nicolas Grekas <p@tchwork.com>
*/
class PhpArrayCache implements CacheInterface
class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInterface
{
use PhpArrayTrait;
@ -33,7 +35,7 @@ class PhpArrayCache implements CacheInterface
public function __construct($file, CacheInterface $fallbackPool)
{
$this->file = $file;
$this->fallbackPool = $fallbackPool;
$this->pool = $fallbackPool;
$this->zendDetectUnicode = ini_get('zend.detect_unicode');
}
@ -68,7 +70,7 @@ class PhpArrayCache implements CacheInterface
$this->initialize();
}
if (!isset($this->values[$key])) {
return $this->fallbackPool->get($key, $default);
return $this->pool->get($key, $default);
}
$value = $this->values[$key];
@ -124,7 +126,7 @@ class PhpArrayCache implements CacheInterface
$this->initialize();
}
return isset($this->values[$key]) || $this->fallbackPool->has($key);
return isset($this->values[$key]) || $this->pool->has($key);
}
/**
@ -139,7 +141,7 @@ class PhpArrayCache implements CacheInterface
$this->initialize();
}
return !isset($this->values[$key]) && $this->fallbackPool->delete($key);
return !isset($this->values[$key]) && $this->pool->delete($key);
}
/**
@ -170,7 +172,7 @@ class PhpArrayCache implements CacheInterface
}
if ($fallbackKeys) {
$deleted = $this->fallbackPool->deleteMultiple($fallbackKeys) && $deleted;
$deleted = $this->pool->deleteMultiple($fallbackKeys) && $deleted;
}
return $deleted;
@ -188,7 +190,7 @@ class PhpArrayCache implements CacheInterface
$this->initialize();
}
return !isset($this->values[$key]) && $this->fallbackPool->set($key, $value, $ttl);
return !isset($this->values[$key]) && $this->pool->set($key, $value, $ttl);
}
/**
@ -216,7 +218,7 @@ class PhpArrayCache implements CacheInterface
}
if ($fallbackValues) {
$saved = $this->fallbackPool->setMultiple($fallbackValues, $ttl) && $saved;
$saved = $this->pool->setMultiple($fallbackValues, $ttl) && $saved;
}
return $saved;
@ -249,7 +251,7 @@ class PhpArrayCache implements CacheInterface
}
if ($fallbackKeys) {
foreach ($this->fallbackPool->getMultiple($fallbackKeys, $default) as $key => $item) {
foreach ($this->pool->getMultiple($fallbackKeys, $default) as $key => $item) {
yield $key => $item;
}
}

View File

@ -18,13 +18,17 @@ use Psr\SimpleCache\CacheException as SimpleCacheException;
use Symfony\Component\Cache\Adapter\AbstractAdapter;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\ProxyTrait;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class Psr6Cache implements CacheInterface
class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterface
{
private $pool;
use ProxyTrait;
private $createCacheItem;
public function __construct(CacheItemPoolInterface $pool)

View File

@ -12,13 +12,15 @@
namespace Symfony\Component\Cache\Simple;
use Psr\SimpleCache\CacheInterface;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
/**
* An adapter that collects data about all cache calls.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class TraceableCache implements CacheInterface
class TraceableCache implements CacheInterface, PruneableInterface, ResettableInterface
{
private $pool;
private $miss;
@ -177,6 +179,38 @@ class TraceableCache implements CacheInterface
}
}
/**
* {@inheritdoc}
*/
public function prune()
{
if (!$this->pool instanceof PruneableInterface) {
return false;
}
$event = $this->start(__FUNCTION__);
try {
return $event->result = $this->pool->prune();
} finally {
$event->end = microtime(true);
}
}
/**
* {@inheritdoc}
*/
public function reset()
{
if (!$this->pool instanceof ResettableInterface) {
return;
}
$event = $this->start(__FUNCTION__);
try {
$this->pool->reset();
} finally {
$event->end = microtime(true);
}
}
public function getCalls()
{
try {

View File

@ -50,6 +50,7 @@ class PhpArrayAdapterTest extends AdapterTestCase
'testDeleteItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.',
'testDefaultLifeTime' => 'PhpArrayAdapter does not allow configuring a default lifetime.',
'testPrune' => 'PhpArrayAdapter just proxies',
);
protected static $file;

View File

@ -25,6 +25,7 @@ class PhpArrayAdapterWithFallbackTest extends AdapterTestCase
'testHasItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.',
'testDeleteItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.',
'testDeleteItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.',
'testPrune' => 'PhpArrayAdapter just proxies',
);
protected static $file;

View File

@ -24,6 +24,7 @@ class ProxyAdapterTest extends AdapterTestCase
protected $skippedTests = array(
'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayAdapter is not.',
'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayAdapter is not.',
'testPrune' => 'ProxyAdapter just proxies',
);
public function createCachePool($defaultLifetime = 0)

View File

@ -19,6 +19,10 @@ use Symfony\Component\Cache\Adapter\SimpleCacheAdapter;
*/
class SimpleCacheAdapterTest extends AdapterTestCase
{
protected $skippedTests = array(
'testPrune' => 'SimpleCache just proxies',
);
public function createCachePool($defaultLifetime = 0)
{
return new SimpleCacheAdapter(new FilesystemCache(), '', $defaultLifetime);

View File

@ -19,6 +19,10 @@ use Symfony\Component\Cache\Adapter\TraceableAdapter;
*/
class TraceableAdapterTest extends AdapterTestCase
{
protected $skippedTests = array(
'testPrune' => 'TraceableAdapter just proxies',
);
public function createCachePool($defaultLifetime = 0)
{
return new TraceableAdapter(new FilesystemAdapter('', $defaultLifetime));

View File

@ -44,6 +44,7 @@ class PhpArrayCacheTest extends CacheTestCase
'testSetValidData' => 'PhpArrayCache does no validation',
'testDefaultLifeTime' => 'PhpArrayCache does not allow configuring a default lifetime.',
'testPrune' => 'PhpArrayCache just proxies',
);
protected static $file;

View File

@ -31,6 +31,7 @@ class PhpArrayCacheWithFallbackTest extends CacheTestCase
'testSetMultipleInvalidKeys' => 'PhpArrayCache does no validation',
'testSetMultipleInvalidTtl' => 'PhpArrayCache does no validation',
'testHasInvalidKeys' => 'PhpArrayCache does no validation',
'testPrune' => 'PhpArrayCache just proxies',
);
protected static $file;

View File

@ -19,6 +19,10 @@ use Symfony\Component\Cache\Simple\Psr6Cache;
*/
class Psr6CacheTest extends CacheTestCase
{
protected $skippedTests = array(
'testPrune' => 'Psr6Cache just proxies',
);
public function createSimpleCache($defaultLifetime = 0)
{
return new Psr6Cache(new FilesystemAdapter('', $defaultLifetime));

View File

@ -19,6 +19,10 @@ use Symfony\Component\Cache\Simple\TraceableCache;
*/
class TraceableCacheTest extends CacheTestCase
{
protected $skippedTests = array(
'testPrune' => 'TraceableCache just proxies',
);
public function createSimpleCache($defaultLifetime = 0)
{
return new TraceableCache(new FilesystemCache('', $defaultLifetime));

View File

@ -189,6 +189,17 @@ trait AbstractTrait
return $wasEnabled;
}
/**
* {@inheritdoc}
*/
public function reset()
{
if ($this->deferred) {
$this->commit();
}
$this->namespaceVersion = '';
}
/**
* Like the native unserialize() function but throws an exception if anything goes wrong.
*

View File

@ -69,6 +69,14 @@ trait ArrayTrait
return true;
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->clear();
}
private function generateItems(array $keys, $now, $f)
{
foreach ($keys as $i => $key) {

View File

@ -20,6 +20,15 @@ trait DoctrineTrait
{
private $provider;
/**
* {@inheritdoc}
*/
public function reset()
{
parent::reset();
$this->provider->setNamespace($this->provider->getNamespace());
}
/**
* {@inheritdoc}
*/

View File

@ -22,9 +22,10 @@ use Symfony\Component\Cache\Exception\InvalidArgumentException;
*/
trait PhpArrayTrait
{
use ProxyTrait;
private $file;
private $values;
private $fallbackPool;
private $zendDetectUnicode;
/**
@ -119,7 +120,7 @@ EOF;
$cleared = @unlink($this->file) || !file_exists($this->file);
return $this->fallbackPool->clear() && $cleared;
return $this->pool->clear() && $cleared;
}
/**

View File

@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Cache\Traits;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
trait ProxyTrait
{
private $pool;
/**
* {@inheritdoc}
*/
public function prune()
{
return $this->pool instanceof PruneableInterface && $this->pool->prune();
}
/**
* {@inheritdoc}
*/
public function reset()
{
if ($this->pool instanceof ResettableInterface) {
$this->pool->reset();
}
}
}