Skip to content

Commit

Permalink
EZP-29427: Add Persistence Cache tag for content versions for clearin…
Browse files Browse the repository at this point in the history
…g before preview, and more (ezsystems#2396)

* [SPI][Cache] Add tag for versions for clearing before preview

* [SPI][Cache] Try to narrow cache clearing on content updates using the new version tag

* Adjust for review comments
  • Loading branch information
andrerom committed Jul 19, 2018
1 parent b0c9201 commit 6205a55
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 22 deletions.
3 changes: 3 additions & 0 deletions doc/specifications/cache/persistence/Readme.md
Expand Up @@ -17,6 +17,9 @@ List of tags and their meaning:
- `content-<content-id>` :
_Meta tag used on anything that are affected on changes to content, on content itself as well as location and so on._

- `content-<content-id>-version-<version-number>`
_Used for specific versions, usuefull for clearing cache of a specific draft on changes for instance._

- `content-fields-<content-id>` :
_Used on content/user object itself (with fields), for use when operations affects field values but not content meta info._

Expand Down
51 changes: 33 additions & 18 deletions eZ/Publish/Core/Persistence/Cache/ContentHandler.php
Expand Up @@ -43,7 +43,7 @@ public function createDraftFromVersion($contentId, $srcVersion, $userId)
{
$this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $srcVersion, 'user' => $userId));
$draft = $this->persistenceHandler->contentHandler()->createDraftFromVersion($contentId, $srcVersion, $userId);
$this->cache->invalidateTags(["content-$contentId-version-list"]);
$this->cache->invalidateTags(["content-{$contentId}-version-list"]);

return $draft;
}
Expand Down Expand Up @@ -72,7 +72,7 @@ public function load($contentId, $versionNo, array $translations = null)
$this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo, 'translations' => $translations));
$content = $this->persistenceHandler->contentHandler()->load($contentId, $versionNo, $translations);
$cacheItem->set($content);
$cacheItem->tag($this->getCacheTags($content->versionInfo->contentInfo, true));
$cacheItem->tag($this->getCacheTagsForContent($content));
$this->cache->save($cacheItem);

return $content;
Expand Down Expand Up @@ -106,7 +106,7 @@ function (array $cacheMissIds) use ($contentLoadStructs) {
return $this->persistenceHandler->contentHandler()->loadContentList($filteredStructs);
},
function (Content $content) {
return $this->getCacheTags($content->versionInfo->contentInfo, true);
return $this->getCacheTagsForContent($content);
},
$keySuffixes
);
Expand Down Expand Up @@ -179,7 +179,7 @@ public function loadVersionInfo($contentId, $versionNo)
$this->logger->logCall(__METHOD__, ['content' => $contentId, 'version' => $versionNo]);
$versionInfo = $this->persistenceHandler->contentHandler()->loadVersionInfo($contentId, $versionNo);
$cacheItem->set($versionInfo);
$cacheItem->tag($this->getCacheTags($versionInfo->contentInfo));
$cacheItem->tag($this->getCacheTagsForVersion($versionInfo));
$this->cache->save($cacheItem);

return $versionInfo;
Expand All @@ -203,11 +203,10 @@ public function setStatus($contentId, $status, $versionNo)
$this->logger->logCall(__METHOD__, array('content' => $contentId, 'status' => $status, 'version' => $versionNo));
$return = $this->persistenceHandler->contentHandler()->setStatus($contentId, $status, $versionNo);

$this->cache->deleteItem("ez-content-version-info-${contentId}-${versionNo}");
if ($status === VersionInfo::STATUS_PUBLISHED) {
$this->cache->invalidateTags(['content-' . $contentId]);
} else {
$this->cache->invalidateTags(["content-$contentId-version-list"]);
$this->cache->invalidateTags(["content-{$contentId}-version-{$versionNo}"]);
}

return $return;
Expand All @@ -232,7 +231,7 @@ public function updateContent($contentId, $versionNo, UpdateStruct $struct)
{
$this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo, 'struct' => $struct));
$content = $this->persistenceHandler->contentHandler()->updateContent($contentId, $versionNo, $struct);
$this->cache->invalidateTags(['content-' . $contentId]);
$this->cache->invalidateTags(["content-{$contentId}-version-{$versionNo}"]);

return $content;
}
Expand Down Expand Up @@ -275,7 +274,7 @@ public function deleteVersion($contentId, $versionNo)
{
$this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo));
$return = $this->persistenceHandler->contentHandler()->deleteVersion($contentId, $versionNo);
$this->cache->invalidateTags(['content-' . $contentId]);
$this->cache->invalidateTags(["content-{$contentId}-version-{$versionNo}"]);

return $return;
}
Expand All @@ -293,8 +292,11 @@ public function listVersions($contentId, $status = null, $limit = -1)
$this->logger->logCall(__METHOD__, array('content' => $contentId, 'status' => $status));
$versions = $this->persistenceHandler->contentHandler()->listVersions($contentId, $status, $limit);
$cacheItem->set($versions);
$tags = ["content-$contentId", "content-$contentId-version-list"];
$cacheItem->tag(empty($versions) ? $tags : $this->getCacheTags($versions[0]->contentInfo, false, $tags));
$tags = ["content-{$contentId}", "content-{$contentId}-version-list"];
foreach ($versions as $version) {
$tags = $this->getCacheTagsForVersion($version, $tags);
}
$cacheItem->tag($tags);
$this->cache->save($cacheItem);

return $versions;
Expand Down Expand Up @@ -397,7 +399,7 @@ public function deleteTranslationFromDraft($contentId, $versionNo, $languageCode
$versionNo,
$languageCode
);
$this->cache->invalidateTags(['content-' . $contentId]);
$this->cache->invalidateTags(["content-{$contentId}-version-{$versionNo}"]);

return $content;
}
Expand All @@ -408,20 +410,14 @@ public function deleteTranslationFromDraft($contentId, $versionNo, $languageCode
* For use when generating cache, not on invalidation.
*
* @param \eZ\Publish\SPI\Persistence\Content\ContentInfo $contentInfo
* @param bool $withFields Set to true if item contains fields which should be expired on relation or type updates.
* @param array $tags Optional, can be used to specify other tags.
*
* @return array
*/
private function getCacheTags(ContentInfo $contentInfo, $withFields = false, array $tags = [])
private function getCacheTags(ContentInfo $contentInfo, array $tags = [])
{
$tags[] = 'content-' . $contentInfo->id;

if ($withFields) {
$tags[] = 'content-fields-' . $contentInfo->id;
$tags[] = 'content-fields-type-' . $contentInfo->contentTypeId;
}

if ($contentInfo->mainLocationId) {
$locations = $this->persistenceHandler->locationHandler()->loadLocationsByContent($contentInfo->id);
foreach ($locations as $location) {
Expand All @@ -434,4 +430,23 @@ private function getCacheTags(ContentInfo $contentInfo, $withFields = false, arr

return array_unique($tags);
}

private function getCacheTagsForVersion(VersionInfo $versionInfo, array $tags = [])
{
$contentInfo = $versionInfo->contentInfo;
$tags[] = 'content-' . $contentInfo->id . '-version-' . $versionInfo->versionNo;

return $this->getCacheTags($contentInfo, $tags);
}

private function getCacheTagsForContent(Content $content)
{
$versionInfo = $content->versionInfo;
$tags = [
'content-fields-' . $versionInfo->contentInfo->id,
'content-fields-type-' . $versionInfo->contentInfo->contentTypeId,
];

return $this->getCacheTagsForVersion($versionInfo, $tags);
}
}
Expand Up @@ -46,12 +46,12 @@ public function providerForUnCachedMethods(): array
['createDraftFromVersion', [2, 1, 14], ['content-2-version-list']],
['copy', [2, 1]],
['loadDraftsForUser', [14]],
['setStatus', [2, 0, 1], ['content-2-version-list'], 'ez-content-version-info-2-1'],
['setStatus', [2, 1, 1], ['content-2'], 'ez-content-version-info-2-1'],
['setStatus', [2, 0, 1], ['content-2-version-1']],
['setStatus', [2, 1, 1], ['content-2']],
['updateMetadata', [2, new MetadataUpdateStruct()], ['content-2']],
['updateContent', [2, 1, new UpdateStruct()], ['content-2']],
['updateContent', [2, 1, new UpdateStruct()], ['content-2-version-1']],
//['deleteContent', [2]], own tests for relations complexity
['deleteVersion', [2, 1], ['content-2']],
['deleteVersion', [2, 1], ['content-2-version-1']],
['addRelation', [new RelationCreateStruct()]],
['removeRelation', [66, APIRelation::COMMON]],
['loadRelations', [2, 1, 3]],
Expand Down

0 comments on commit 6205a55

Please sign in to comment.