Page MenuHomePhabricator

D10600.diff
No OneTemporary

D10600.diff

diff --git a/src/applications/diffusion/query/blame/DiffusionBlameQuery.php b/src/applications/diffusion/query/blame/DiffusionBlameQuery.php
--- a/src/applications/diffusion/query/blame/DiffusionBlameQuery.php
+++ b/src/applications/diffusion/query/blame/DiffusionBlameQuery.php
@@ -34,9 +34,35 @@
final protected function executeQuery() {
$paths = $this->getPaths();
+
+ $blame = array();
+
+ // Load cache keys: these are the commits at which each path was last
+ // touched.
+ $keys = $this->loadCacheKeys($paths);
+
+ // Try to read blame data from cache.
+ $cache = $this->readCacheData($keys);
+ foreach ($paths as $key => $path) {
+ if (!isset($cache[$path])) {
+ continue;
+ }
+
+ $blame[$path] = $cache[$path];
+ unset($paths[$key]);
+ }
+
+ // If we have no paths left, we filled everything from cache and can
+ // bail out early.
+ if (!$paths) {
+ return $blame;
+ }
+
$request = $this->getRequest();
$timeout = $this->getTimeout();
+ // We're still missing at least some data, so we need to run VCS commands
+ // to pull it.
$futures = array();
foreach ($paths as $path) {
$future = $this->newBlameFuture($request, $path);
@@ -48,22 +74,107 @@
$futures[$path] = $future;
}
+ $futures = id(new FutureIterator($futures))
+ ->limit(4);
- $blame = array();
+ foreach ($futures as $path => $future) {
+ $path_blame = $this->resolveBlameFuture($future);
+ if ($path_blame !== null) {
+ $blame[$path] = $path_blame;
+ }
+ }
+
+ // Fill the cache with anything we generated.
+ $this->writeCacheData(
+ array_select_keys($keys, $paths),
+ $blame);
- if ($futures) {
- $futures = id(new FutureIterator($futures))
- ->limit(4);
+ return $blame;
+ }
- foreach ($futures as $path => $future) {
- $path_blame = $this->resolveBlameFuture($future);
- if ($path_blame !== null) {
- $blame[$path] = $path_blame;
- }
+ private function loadCacheKeys(array $paths) {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $repository = $request->getRepository();
+ $repository_id = $repository->getID();
+
+ $last_modified = parent::callConduitWithDiffusionRequest(
+ $viewer,
+ $request,
+ 'diffusion.lastmodifiedquery',
+ array(
+ 'paths' => array_fill_keys($paths, $request->getCommit()),
+ ));
+
+ $map = array();
+ foreach ($paths as $path) {
+ $identifier = idx($last_modified, $path);
+ if ($identifier === null) {
+ continue;
}
+
+ $map[$path] = "blame({$repository_id}, {$identifier}, {$path}, raw)";
}
- return $blame;
+ return $map;
+ }
+
+ private function readCacheData(array $keys) {
+ $cache = PhabricatorCaches::getImmutableCache();
+ $data = $cache->getKeys($keys);
+
+ $results = array();
+ foreach ($keys as $path => $key) {
+ if (!isset($data[$key])) {
+ continue;
+ }
+ $results[$path] = $data[$key];
+ }
+
+ // Decode the cache storage format.
+ foreach ($results as $path => $cache) {
+ list($head, $body) = explode("\n", $cache, 2);
+ switch ($head) {
+ case 'raw':
+ $body = explode("\n", $body);
+ break;
+ default:
+ $body = null;
+ break;
+ }
+
+ if ($body === null) {
+ unset($results[$path]);
+ } else {
+ $results[$path] = $body;
+ }
+ }
+
+ return $results;
+ }
+
+ private function writeCacheData(array $keys, array $blame) {
+ $writes = array();
+ foreach ($keys as $path => $key) {
+ $value = idx($blame, $path);
+ if ($value === null) {
+ continue;
+ }
+
+ // For now, just store the entire value with a "raw" header. In the
+ // future, we could compress this or use IDs instead.
+ $value = "raw\n".implode("\n", $value);
+
+ $writes[$key] = $value;
+ }
+
+ if (!$writes) {
+ return;
+ }
+
+ $cache = PhabricatorCaches::getImmutableCache();
+ $data = $cache->setKeys($writes, phutil_units('14 days in seconds'));
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryQuery.php b/src/applications/repository/query/PhabricatorRepositoryQuery.php
--- a/src/applications/repository/query/PhabricatorRepositoryQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryQuery.php
@@ -49,6 +49,8 @@
}
public function withIdentifiers(array $identifiers) {
+ $identifiers = array_fuse($identifiers);
+
$ids = array();
$callsigns = array();
$phids = array();

File Metadata

Mime Type
text/plain
Expires
Sun, May 12, 4:20 AM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6268191
Default Alt Text
D10600.diff (4 KB)

Event Timeline