Commit 5d0ae283 authored by epriestley's avatar epriestley
Browse files

Put a readthrough cache in front of inline context construction

Summary: Ref T13513. Inline comment context information is somewhat expensive to construct and can be cached. Add a readthrough cache on top of it.

Test Plan: Loaded a source code changeset with many inline comments, used Darkconsole to inspect query activity. Saw caches get populated. Updated cache key, saw caches regenerate. Browsed Diffusion, nothing looked broken.

Maniphest Tasks: T13513

Differential Revision: https://secure.phabricator.com/D21279
parent d2d7e7f5
......@@ -67,17 +67,26 @@ final class DifferentialDiffInlineCommentQuery
return $id_map;
}
protected function newInlineContextFromCacheData(array $map) {
return PhabricatorDiffInlineCommentContext::newFromCacheData($map);
}
protected function newInlineContextMap(array $inlines) {
$viewer = $this->getViewer();
$map = array();
$changeset_ids = mpull($inlines, 'getChangesetID');
$changesets = id(new DifferentialChangesetQuery())
->setViewer($viewer)
->withIDs($changeset_ids)
->needHunks(true)
->execute();
$changesets = mpull($changesets, null, 'getID');
foreach ($inlines as $key => $inline) {
$changeset = id(new DifferentialChangesetQuery())
->setViewer($viewer)
->withIDs(array($inline->getChangesetID()))
->needHunks(true)
->executeOne();
$changeset = idx($changesets, $inline->getChangesetID());
if (!$changeset) {
continue;
}
......
......@@ -70,4 +70,8 @@ final class DiffusionDiffInlineCommentQuery
return array();
}
protected function newInlineContextFromCacheData(array $map) {
return PhabricatorDiffInlineCommentContext::newFromCacheData($map);
}
}
......@@ -8,6 +8,26 @@ final class PhabricatorDiffInlineCommentContext
private $bodyLines;
private $tailLines;
public static function newFromCacheData(array $map) {
$context = new self();
$context->setFilename(idx($map, 'filename'));
$context->setHeadLines(idx($map, 'headLines'));
$context->setBodyLines(idx($map, 'bodyLines'));
$context->setTailLines(idx($map, 'tailLines'));
return $context;
}
public function newCacheDataMap() {
return array(
'filename' => $this->getFilename(),
'headLines' => $this->getHeadLines(),
'bodyLines' => $this->getBodyLines(),
'tailLines' => $this->getTailLines(),
);
}
public function setFilename($filename) {
$this->filename = $filename;
return $this;
......
......@@ -82,6 +82,16 @@ abstract class PhabricatorInlineComment
return $this->storageObject;
}
public function getInlineCommentCacheFragment() {
$phid = $this->getPHID();
if ($phid === null) {
return null;
}
return sprintf('inline(%s)', $phid);
}
abstract protected function newStorageObject();
abstract public function getControllerURI();
......
......@@ -3,6 +3,8 @@
abstract class PhabricatorDiffInlineCommentQuery
extends PhabricatorApplicationTransactionCommentQuery {
const INLINE_CONTEXT_CACHE_VERSION = 1;
private $fixedStates;
private $needReplyToComments;
private $publishedComments;
......@@ -19,6 +21,7 @@ abstract class PhabricatorDiffInlineCommentQuery
array $comments);
abstract protected function newInlineContextMap(array $inlines);
abstract protected function newInlineContextFromCacheData(array $map);
final public function withFixedStates(array $states) {
$this->fixedStates = $states;
......@@ -268,16 +271,83 @@ abstract class PhabricatorDiffInlineCommentQuery
}
if ($need_context) {
$context_map = $this->newInlineContextMap($need_context);
$this->loadInlineCommentContext($need_context);
}
}
return $inlines;
}
private function loadInlineCommentContext(array $inlines) {
$cache_keys = array();
foreach ($inlines as $key => $inline) {
$object = $inline->newInlineCommentObject();
$fragment = $object->getInlineCommentCacheFragment();
if ($fragment === null) {
continue;
}
$cache_keys[$key] = sprintf(
'%s.context(v%d)',
$fragment,
self::INLINE_CONTEXT_CACHE_VERSION);
}
$cache = PhabricatorCaches::getMutableStructureCache();
$cache_map = $cache->getKeys($cache_keys);
$context_map = array();
$need_construct = array();
foreach ($inlines as $key => $inline) {
$cache_key = idx($cache_keys, $key);
foreach ($need_context as $key => $inline) {
$inline->attachInlineContext(idx($context_map, $key));
if ($cache_key !== null) {
if (array_key_exists($cache_key, $cache_map)) {
$cache_data = $cache_map[$cache_key];
$context_map[$key] = $this->newInlineContextFromCacheData(
$cache_data);
continue;
}
}
$need_construct[$key] = $inline;
}
return $inlines;
if ($need_construct) {
$construct_map = $this->newInlineContextMap($need_construct);
$write_map = array();
foreach ($construct_map as $key => $context) {
if ($context === null) {
$cache_data = $context;
} else {
$cache_data = $this->newCacheDataFromInlineContext($context);
}
$cache_key = idx($cache_keys, $key);
if ($cache_key !== null) {
$write_map[$cache_key] = $cache_data;
}
}
if ($write_map) {
$cache->setKeys($write_map);
}
$context_map += $construct_map;
}
foreach ($inlines as $key => $inline) {
$inline->attachInlineContext(idx($context_map, $key));
}
}
protected function newCacheDataFromInlineContext(
PhabricatorInlineCommentContext $context) {
return $context->newCacheDataMap();
}
final protected function simplifyContext(array $lines, $is_head) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment