Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f538f57

Browse files
[Cache] TagAwareAdapterInterface::invalidateTags() should commit deferred items
1 parent ea25fec commit f538f57

File tree

2 files changed

+97
-42
lines changed

2 files changed

+97
-42
lines changed

src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php

Lines changed: 81 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R
3333
private $getTagsByKey;
3434
private $invalidateTags;
3535
private $tags;
36+
private $knownTagVersions = array();
37+
private $knownTagVersionsTtl;
3638

37-
public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null)
39+
public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, $knownTagVersionsTtl = 0.15)
3840
{
3941
$this->pool = $itemsPool;
4042
$this->tags = $tagsPool ?: $itemsPool;
43+
$this->knownTagVersionsTtl = $knownTagVersionsTtl;
4144
$this->createCacheItem = \Closure::bind(
4245
function ($key, $value, CacheItem $protoItem) {
4346
$item = new CacheItem();
@@ -87,8 +90,7 @@ function ($deferred) {
8790
);
8891
$this->invalidateTags = \Closure::bind(
8992
function (AdapterInterface $tagsAdapter, array $tags) {
90-
foreach ($tagsAdapter->getItems($tags) as $v) {
91-
$v->set(1 + (int) $v->get());
93+
foreach ($tags as $v) {
9294
$v->defaultLifetime = 0;
9395
$v->expiry = null;
9496
$tagsAdapter->saveDeferred($v);
@@ -106,14 +108,42 @@ function (AdapterInterface $tagsAdapter, array $tags) {
106108
*/
107109
public function invalidateTags(array $tags)
108110
{
109-
foreach ($tags as $k => $tag) {
110-
if ('' !== $tag && \is_string($tag)) {
111-
$tags[$k] = $tag.static::TAGS_PREFIX;
111+
$ok = true;
112+
$tagsByKey = array();
113+
$invalidatedTags = array();
114+
foreach ($tags as $tag) {
115+
CacheItem::validateKey($tag);
116+
$invalidatedTags[$tag] = 0;
117+
}
118+
119+
if ($this->deferred) {
120+
$items = $this->deferred;
121+
foreach ($items as $key => $item) {
122+
if (!$this->pool->saveDeferred($item)) {
123+
unset($this->deferred[$key]);
124+
$ok = false;
125+
}
112126
}
127+
128+
$f = $this->getTagsByKey;
129+
$tagsByKey = $f($items);
130+
$this->deferred = array();
131+
}
132+
133+
$tagVersions = $this->getTagVersions($tagsByKey, $invalidatedTags);
134+
$f = $this->createCacheItem;
135+
136+
foreach ($tagsByKey as $key => $tags) {
137+
$this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
138+
}
139+
$ok = $this->pool->commit() && $ok;
140+
141+
if ($invalidatedTags) {
142+
$f = $this->invalidateTags;
143+
$ok = $f($this->tags, $invalidatedTags) && $ok;
113144
}
114-
$f = $this->invalidateTags;
115145

116-
return $f($this->tags, $tags);
146+
return $ok;
117147
}
118148

119149
/**
@@ -132,7 +162,7 @@ public function hasItem($key)
132162
}
133163

134164
foreach ($this->getTagVersions(array($itemTags)) as $tag => $version) {
135-
if ($itemTags[$tag] !== $version) {
165+
if ($itemTags[$tag] !== $version && 1 !== $itemTags[$tag] - $version) {
136166
return false;
137167
}
138168
}
@@ -241,29 +271,7 @@ public function saveDeferred(CacheItemInterface $item)
241271
*/
242272
public function commit()
243273
{
244-
$ok = true;
245-
246-
if ($this->deferred) {
247-
$items = $this->deferred;
248-
foreach ($items as $key => $item) {
249-
if (!$this->pool->saveDeferred($item)) {
250-
unset($this->deferred[$key]);
251-
$ok = false;
252-
}
253-
}
254-
255-
$f = $this->getTagsByKey;
256-
$tagsByKey = $f($items);
257-
$this->deferred = array();
258-
$tagVersions = $this->getTagVersions($tagsByKey);
259-
$f = $this->createCacheItem;
260-
261-
foreach ($tagsByKey as $key => $tags) {
262-
$this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
263-
}
264-
}
265-
266-
return $this->pool->commit() && $ok;
274+
return $this->invalidateTags(array());
267275
}
268276

269277
public function __destruct()
@@ -294,7 +302,7 @@ private function generateItems($items, array $tagKeys)
294302

295303
foreach ($itemTags as $key => $tags) {
296304
foreach ($tags as $tag => $version) {
297-
if ($tagVersions[$tag] !== $version) {
305+
if ($tagVersions[$tag] !== $version && 1 !== $version - $tagVersions[$tag]) {
298306
unset($itemTags[$key]);
299307
continue 2;
300308
}
@@ -310,23 +318,54 @@ private function generateItems($items, array $tagKeys)
310318
}
311319
}
312320

313-
private function getTagVersions(array $tagsByKey)
321+
private function getTagVersions(array $tagsByKey, array &$invalidatedTags = array())
314322
{
315-
$tagVersions = array();
323+
$tagVersions = $invalidatedTags;
316324

317325
foreach ($tagsByKey as $tags) {
318326
$tagVersions += $tags;
319327
}
320328

321-
if ($tagVersions) {
322-
$tags = array();
323-
foreach ($tagVersions as $tag => $version) {
324-
$tagVersions[$tag] = $tag.static::TAGS_PREFIX;
325-
$tags[$tag.static::TAGS_PREFIX] = $tag;
329+
if (!$tagVersions) {
330+
return array();
331+
}
332+
333+
if (!$fetchTagVersions = 1 !== \func_num_args()) {
334+
foreach ($tagsByKey as $tags) {
335+
foreach ($tags as $tag => $version) {
336+
if ($tagVersions[$tag] > $version) {
337+
$tagVersions[$tag] = $version;
338+
}
339+
}
340+
}
341+
}
342+
343+
$now = microtime(true);
344+
$tags = array();
345+
foreach ($tagVersions as $tag => $version) {
346+
$tags[$tag.static::TAGS_PREFIX] = $tag;
347+
if ($fetchTagVersions || !isset($this->knownTagVersions[$tag])) {
348+
continue;
349+
}
350+
$version -= $this->knownTagVersions[$tag][1];
351+
if ((0 !== $version && 1 !== $version) || $this->knownTagVersionsTtl > $now - $this->knownTagVersions[$tag][0]) {
352+
// reuse previously fetched tag versions up to the ttl, unless we are storing items or a potential miss arises
353+
$fetchTagVersions = true;
354+
} else {
355+
$this->knownTagVersions[$tag][1] += $version;
326356
}
327-
foreach ($this->tags->getItems($tagVersions) as $tag => $version) {
328-
$tagVersions[$tags[$tag]] = $version->get() ?: 0;
357+
}
358+
359+
if (!$fetchTagVersions) {
360+
return $tagVersions;
361+
}
362+
363+
foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) {
364+
$tagVersions[$tag = $tags[$tag]] = $version->get() ?: 0;
365+
if (isset($invalidatedTags[$tag])) {
366+
$invalidatedTags[$tag] = $version->set(++$tagVersions[$tag]);
329367
}
368+
$this->knownTagVersions[$tag] = array($now, $tagVersions[$tag]);
330369
}
331370

332371
return $tagVersions;

src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,22 @@ public function testInvalidateTags()
7171
$this->assertTrue($pool->getItem('foo')->isHit());
7272
}
7373

74+
public function testInvalidateCommits()
75+
{
76+
$pool1 = $this->createCachePool();
77+
78+
$foo = $pool1->getItem('foo');
79+
$foo->tag('tag');
80+
81+
$pool1->saveDeferred($foo->set('foo'));
82+
$pool1->invalidateTags(array('foo'));
83+
84+
$pool2 = $this->createCachePool();
85+
$foo = $pool2->getItem('foo');
86+
87+
$this->assertTrue($foo->isHit());
88+
}
89+
7490
public function testTagsAreCleanedOnSave()
7591
{
7692
$pool = $this->createCachePool();

0 commit comments

Comments
 (0)