Path: blob/master/src/applications/fact/daemon/PhabricatorFactDaemon.php
12256 views
<?php12final class PhabricatorFactDaemon extends PhabricatorDaemon {34private $engines;56protected function run() {7$this->setEngines(PhabricatorFactEngine::loadAllEngines());8do {9PhabricatorCaches::destroyRequestCache();1011$iterators = $this->getAllApplicationIterators();12foreach ($iterators as $iterator_name => $iterator) {13$this->processIteratorWithCursor($iterator_name, $iterator);14}1516$sleep_duration = 60;1718if ($this->shouldHibernate($sleep_duration)) {19break;20}2122$this->sleep($sleep_duration);23} while (!$this->shouldExit());24}2526public static function getAllApplicationIterators() {27$apps = PhabricatorApplication::getAllInstalledApplications();2829$iterators = array();30foreach ($apps as $app) {31foreach ($app->getFactObjectsForAnalysis() as $object) {32$iterator = new PhabricatorFactUpdateIterator($object);33$iterators[get_class($object)] = $iterator;34}35}3637return $iterators;38}3940public function processIteratorWithCursor($iterator_name, $iterator) {41$this->log(pht("Processing cursor '%s'.", $iterator_name));4243$cursor = id(new PhabricatorFactCursor())->loadOneWhere(44'name = %s',45$iterator_name);46if (!$cursor) {47$cursor = new PhabricatorFactCursor();48$cursor->setName($iterator_name);49$position = null;50} else {51$position = $cursor->getPosition();52}5354if ($position) {55$iterator->setPosition($position);56}5758$new_cursor_position = $this->processIterator($iterator);5960if ($new_cursor_position) {61$cursor->setPosition($new_cursor_position);62$cursor->save();63}64}6566public function setEngines(array $engines) {67assert_instances_of($engines, 'PhabricatorFactEngine');6869$viewer = PhabricatorUser::getOmnipotentUser();70foreach ($engines as $engine) {71$engine->setViewer($viewer);72}7374$this->engines = $engines;75return $this;76}7778public function processIterator($iterator) {79$result = null;8081$datapoints = array();82$count = 0;83foreach ($iterator as $key => $object) {84$phid = $object->getPHID();85$this->log(pht('Processing %s...', $phid));86$object_datapoints = $this->newDatapoints($object);87$count += count($object_datapoints);8889$datapoints[$phid] = $object_datapoints;9091if ($count > 1024) {92$this->updateDatapoints($datapoints);93$datapoints = array();94$count = 0;95}9697$result = $key;98}99100if ($count) {101$this->updateDatapoints($datapoints);102$datapoints = array();103$count = 0;104}105106return $result;107}108109private function newDatapoints(PhabricatorLiskDAO $object) {110$facts = array();111foreach ($this->engines as $engine) {112if (!$engine->supportsDatapointsForObject($object)) {113continue;114}115$facts[] = $engine->newDatapointsForObject($object);116}117118return array_mergev($facts);119}120121private function updateDatapoints(array $map) {122foreach ($map as $phid => $facts) {123assert_instances_of($facts, 'PhabricatorFactIntDatapoint');124}125126$phids = array_keys($map);127if (!$phids) {128return;129}130131$fact_keys = array();132$objects = array();133foreach ($map as $phid => $facts) {134foreach ($facts as $fact) {135$fact_keys[$fact->getKey()] = true;136137$object_phid = $fact->getObjectPHID();138$objects[$object_phid] = $object_phid;139140$dimension_phid = $fact->getDimensionPHID();141if ($dimension_phid !== null) {142$objects[$dimension_phid] = $dimension_phid;143}144}145}146147$key_map = id(new PhabricatorFactKeyDimension())148->newDimensionMap(array_keys($fact_keys), true);149$object_map = id(new PhabricatorFactObjectDimension())150->newDimensionMap(array_keys($objects), true);151152$table = new PhabricatorFactIntDatapoint();153$conn = $table->establishConnection('w');154$table_name = $table->getTableName();155156$sql = array();157foreach ($map as $phid => $facts) {158foreach ($facts as $fact) {159$key_id = $key_map[$fact->getKey()];160$object_id = $object_map[$fact->getObjectPHID()];161162$dimension_phid = $fact->getDimensionPHID();163if ($dimension_phid !== null) {164$dimension_id = $object_map[$dimension_phid];165} else {166$dimension_id = null;167}168169$sql[] = qsprintf(170$conn,171'(%d, %d, %nd, %d, %d)',172$key_id,173$object_id,174$dimension_id,175$fact->getValue(),176$fact->getEpoch());177}178}179180$rebuilt_ids = array_select_keys($object_map, $phids);181182$table->openTransaction();183184queryfx(185$conn,186'DELETE FROM %T WHERE objectID IN (%Ld)',187$table_name,188$rebuilt_ids);189190if ($sql) {191foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) {192queryfx(193$conn,194'INSERT INTO %T195(keyID, objectID, dimensionID, value, epoch)196VALUES %LQ',197$table_name,198$chunk);199}200}201202$table->saveTransaction();203}204205}206207208