[Cache] Fix tags expiration

This commit is contained in:
Nicolas Grekas 2017-01-18 16:06:43 +01:00
parent 24f0fd0dda
commit c0022f29d6
2 changed files with 43 additions and 16 deletions

View File

@ -26,6 +26,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface
private $deferred = array();
private $createCacheItem;
private $getTagsByKey;
private $invalidateTags;
private $tagsAdapter;
public function __construct(AdapterInterface $itemsAdapter, AdapterInterface $tagsAdapter = null)
@ -33,17 +34,15 @@ class TagAwareAdapter implements TagAwareAdapterInterface
$this->itemsAdapter = $itemsAdapter;
$this->tagsAdapter = $tagsAdapter ?: $itemsAdapter;
$this->createCacheItem = \Closure::bind(
function ($key, $value = null, CacheItem $protoItem = null) {
function ($key, $value, CacheItem $protoItem) {
$item = new CacheItem();
$item->key = $key;
$item->value = $value;
$item->isHit = false;
if (null !== $protoItem) {
$item->defaultLifetime = $protoItem->defaultLifetime;
$item->innerItem = $protoItem->innerItem;
$item->poolHash = $protoItem->poolHash;
}
$item->defaultLifetime = $protoItem->defaultLifetime;
$item->expiry = $protoItem->expiry;
$item->innerItem = $protoItem->innerItem;
$item->poolHash = $protoItem->poolHash;
return $item;
},
@ -62,6 +61,20 @@ class TagAwareAdapter implements TagAwareAdapterInterface
null,
CacheItem::class
);
$this->invalidateTags = \Closure::bind(
function (AdapterInterface $tagsAdapter, array $tags) {
foreach ($tagsAdapter->getItems($tags) as $v) {
$v->set(1 + (int) $v->get());
$v->defaultLifetime = 0;
$v->expiry = null;
$tagsAdapter->saveDeferred($v);
}
return $tagsAdapter->commit();
},
null,
CacheItem::class
);
}
/**
@ -74,13 +87,9 @@ class TagAwareAdapter implements TagAwareAdapterInterface
$tags[$k] = $tag.static::TAGS_PREFIX;
}
}
$f = $this->invalidateTags;
foreach ($this->tagsAdapter->getItems($tags) as $v) {
$v->set(1 + (int) $v->get());
$this->tagsAdapter->saveDeferred($v);
}
return $this->tagsAdapter->commit();
return $f($this->tagsAdapter, $tags);
}
/**
@ -211,7 +220,8 @@ class TagAwareAdapter implements TagAwareAdapterInterface
$ok = true;
if ($this->deferred) {
foreach ($this->deferred as $key => $item) {
$items = $this->deferred;
foreach ($items as $key => $item) {
if (!$this->itemsAdapter->saveDeferred($item)) {
unset($this->deferred[$key]);
$ok = false;
@ -219,14 +229,14 @@ class TagAwareAdapter implements TagAwareAdapterInterface
}
$f = $this->getTagsByKey;
$tagsByKey = $f($this->deferred);
$tagsByKey = $f($items);
$deletedTags = $this->deferred = array();
$tagVersions = $this->getTagVersions($tagsByKey);
$f = $this->createCacheItem;
foreach ($tagsByKey as $key => $tags) {
if ($tags) {
$this->itemsAdapter->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags)));
$this->itemsAdapter->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
} else {
$deletedTags[] = static::TAGS_PREFIX.$key;
}

View File

@ -97,4 +97,21 @@ class TagAwareAdapterTest extends AdapterTestCase
$this->assertTrue($pool->getItem('k')->isHit());
}
public function testTagItemExpiry()
{
$pool = $this->createCachePool(10);
$item = $pool->getItem('foo');
$item->tag(array('baz'));
$item->expiresAfter(100);
$pool->save($item);
$pool->invalidateTags(array('baz'));
$this->assertFalse($pool->getItem('foo')->isHit());
sleep(20);
$this->assertFalse($pool->getItem('foo')->isHit());
}
}