Skip to content

Commit

Permalink
bug #21338 [Cache] Fix tags expiration (nicolas-grekas)
Browse files Browse the repository at this point in the history
This PR was merged into the 3.2 branch.

Discussion
----------

[Cache] Fix tags expiration

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

Commits
-------

c0022f2 [Cache] Fix tags expiration
  • Loading branch information
fabpot committed Jan 19, 2017
2 parents 6283fc4 + c0022f2 commit 922b7c1
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 16 deletions.
42 changes: 26 additions & 16 deletions src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php
Expand Up @@ -26,24 +26,23 @@ class TagAwareAdapter implements TagAwareAdapterInterface
private $deferred = array();
private $createCacheItem;
private $getTagsByKey;
private $invalidateTags;
private $tagsAdapter;

public function __construct(AdapterInterface $itemsAdapter, AdapterInterface $tagsAdapter = null)
{
$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;
},
Expand All @@ -62,6 +61,20 @@ function ($deferred) {
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
);
}

/**
Expand All @@ -74,13 +87,9 @@ public function invalidateTags(array $tags)
$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);
}

/**
Expand Down Expand Up @@ -211,22 +220,23 @@ public function commit()
$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;
}
}

$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;
}
Expand Down
17 changes: 17 additions & 0 deletions src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php
Expand Up @@ -97,4 +97,21 @@ public function testTagsAreCleanedOnDelete()

$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());
}
}

0 comments on commit 922b7c1

Please sign in to comment.