diff --git a/src/applications/differential/query/DifferentialDiffInlineCommentQuery.php b/src/applications/differential/query/DifferentialDiffInlineCommentQuery.php --- a/src/applications/differential/query/DifferentialDiffInlineCommentQuery.php +++ b/src/applications/differential/query/DifferentialDiffInlineCommentQuery.php @@ -67,17 +67,26 @@ 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; } diff --git a/src/applications/diffusion/query/DiffusionDiffInlineCommentQuery.php b/src/applications/diffusion/query/DiffusionDiffInlineCommentQuery.php --- a/src/applications/diffusion/query/DiffusionDiffInlineCommentQuery.php +++ b/src/applications/diffusion/query/DiffusionDiffInlineCommentQuery.php @@ -70,4 +70,8 @@ return array(); } + protected function newInlineContextFromCacheData(array $map) { + return PhabricatorDiffInlineCommentContext::newFromCacheData($map); + } + } diff --git a/src/infrastructure/diff/inline/PhabricatorDiffInlineCommentContext.php b/src/infrastructure/diff/inline/PhabricatorDiffInlineCommentContext.php --- a/src/infrastructure/diff/inline/PhabricatorDiffInlineCommentContext.php +++ b/src/infrastructure/diff/inline/PhabricatorDiffInlineCommentContext.php @@ -8,6 +8,26 @@ 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; diff --git a/src/infrastructure/diff/interface/PhabricatorInlineComment.php b/src/infrastructure/diff/interface/PhabricatorInlineComment.php --- a/src/infrastructure/diff/interface/PhabricatorInlineComment.php +++ b/src/infrastructure/diff/interface/PhabricatorInlineComment.php @@ -82,6 +82,16 @@ 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(); diff --git a/src/infrastructure/diff/query/PhabricatorDiffInlineCommentQuery.php b/src/infrastructure/diff/query/PhabricatorDiffInlineCommentQuery.php --- a/src/infrastructure/diff/query/PhabricatorDiffInlineCommentQuery.php +++ b/src/infrastructure/diff/query/PhabricatorDiffInlineCommentQuery.php @@ -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 @@ 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 @@ } 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) {