Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14758001
D19119.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
38 KB
Referenced Files
None
Subscribers
None
D19119.id.diff
View Options
diff --git a/resources/sql/autopatches/20180218.fact.01.dim.key.sql b/resources/sql/autopatches/20180218.fact.01.dim.key.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180218.fact.01.dim.key.sql
@@ -0,0 +1,5 @@
+CREATE TABLE {$NAMESPACE}_fact.fact_keydimension (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ factKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
+ UNIQUE KEY `key_factkey` (factKey)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20180218.fact.02.dim.obj.sql b/resources/sql/autopatches/20180218.fact.02.dim.obj.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180218.fact.02.dim.obj.sql
@@ -0,0 +1,5 @@
+CREATE TABLE {$NAMESPACE}_fact.fact_objectdimension (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ objectPHID VARBINARY(64) NOT NULL,
+ UNIQUE KEY `key_object` (objectPHID)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20180218.fact.03.data.int.sql b/resources/sql/autopatches/20180218.fact.03.data.int.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180218.fact.03.data.int.sql
@@ -0,0 +1,8 @@
+CREATE TABLE {$NAMESPACE}_fact.fact_intdatapoint (
+ id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ keyID INT UNSIGNED NOT NULL,
+ objectID INT UNSIGNED NOT NULL,
+ dimensionID INT UNSIGNED,
+ value BIGINT SIGNED NOT NULL,
+ epoch INT UNSIGNED NOT NULL
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2907,27 +2907,28 @@
'PhabricatorExternalAccountsSettingsPanel' => 'applications/settings/panel/PhabricatorExternalAccountsSettingsPanel.php',
'PhabricatorExtraConfigSetupCheck' => 'applications/config/check/PhabricatorExtraConfigSetupCheck.php',
'PhabricatorFacebookAuthProvider' => 'applications/auth/provider/PhabricatorFacebookAuthProvider.php',
+ 'PhabricatorFact' => 'applications/fact/fact/PhabricatorFact.php',
'PhabricatorFactAggregate' => 'applications/fact/storage/PhabricatorFactAggregate.php',
'PhabricatorFactApplication' => 'applications/fact/application/PhabricatorFactApplication.php',
'PhabricatorFactChartController' => 'applications/fact/controller/PhabricatorFactChartController.php',
'PhabricatorFactController' => 'applications/fact/controller/PhabricatorFactController.php',
- 'PhabricatorFactCountEngine' => 'applications/fact/engine/PhabricatorFactCountEngine.php',
'PhabricatorFactCursor' => 'applications/fact/storage/PhabricatorFactCursor.php',
'PhabricatorFactDAO' => 'applications/fact/storage/PhabricatorFactDAO.php',
'PhabricatorFactDaemon' => 'applications/fact/daemon/PhabricatorFactDaemon.php',
+ 'PhabricatorFactDimension' => 'applications/fact/storage/PhabricatorFactDimension.php',
'PhabricatorFactEngine' => 'applications/fact/engine/PhabricatorFactEngine.php',
'PhabricatorFactEngineTestCase' => 'applications/fact/engine/__tests__/PhabricatorFactEngineTestCase.php',
'PhabricatorFactHomeController' => 'applications/fact/controller/PhabricatorFactHomeController.php',
- 'PhabricatorFactLastUpdatedEngine' => 'applications/fact/engine/PhabricatorFactLastUpdatedEngine.php',
+ 'PhabricatorFactIntDatapoint' => 'applications/fact/storage/PhabricatorFactIntDatapoint.php',
+ 'PhabricatorFactKeyDimension' => 'applications/fact/storage/PhabricatorFactKeyDimension.php',
'PhabricatorFactManagementAnalyzeWorkflow' => 'applications/fact/management/PhabricatorFactManagementAnalyzeWorkflow.php',
'PhabricatorFactManagementCursorsWorkflow' => 'applications/fact/management/PhabricatorFactManagementCursorsWorkflow.php',
'PhabricatorFactManagementDestroyWorkflow' => 'applications/fact/management/PhabricatorFactManagementDestroyWorkflow.php',
'PhabricatorFactManagementListWorkflow' => 'applications/fact/management/PhabricatorFactManagementListWorkflow.php',
- 'PhabricatorFactManagementStatusWorkflow' => 'applications/fact/management/PhabricatorFactManagementStatusWorkflow.php',
'PhabricatorFactManagementWorkflow' => 'applications/fact/management/PhabricatorFactManagementWorkflow.php',
+ 'PhabricatorFactManiphestTaskEngine' => 'applications/fact/engine/PhabricatorFactManiphestTaskEngine.php',
+ 'PhabricatorFactObjectDimension' => 'applications/fact/storage/PhabricatorFactObjectDimension.php',
'PhabricatorFactRaw' => 'applications/fact/storage/PhabricatorFactRaw.php',
- 'PhabricatorFactSimpleSpec' => 'applications/fact/spec/PhabricatorFactSimpleSpec.php',
- 'PhabricatorFactSpec' => 'applications/fact/spec/PhabricatorFactSpec.php',
'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php',
'PhabricatorFavoritesApplication' => 'applications/favorites/application/PhabricatorFavoritesApplication.php',
'PhabricatorFavoritesController' => 'applications/favorites/controller/PhabricatorFavoritesController.php',
@@ -3716,6 +3717,7 @@
'PhabricatorPirateEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorPirateEnglishTranslation.php',
'PhabricatorPlatformSite' => 'aphront/site/PhabricatorPlatformSite.php',
'PhabricatorPointsEditField' => 'applications/transactions/editfield/PhabricatorPointsEditField.php',
+ 'PhabricatorPointsFact' => 'applications/fact/fact/PhabricatorPointsFact.php',
'PhabricatorPolicies' => 'applications/policy/constants/PhabricatorPolicies.php',
'PhabricatorPolicy' => 'applications/policy/storage/PhabricatorPolicy.php',
'PhabricatorPolicyApplication' => 'applications/policy/application/PhabricatorPolicyApplication.php',
@@ -8433,27 +8435,28 @@
'PhabricatorExternalAccountsSettingsPanel' => 'PhabricatorSettingsPanel',
'PhabricatorExtraConfigSetupCheck' => 'PhabricatorSetupCheck',
'PhabricatorFacebookAuthProvider' => 'PhabricatorOAuth2AuthProvider',
+ 'PhabricatorFact' => 'Phobject',
'PhabricatorFactAggregate' => 'PhabricatorFactDAO',
'PhabricatorFactApplication' => 'PhabricatorApplication',
'PhabricatorFactChartController' => 'PhabricatorFactController',
'PhabricatorFactController' => 'PhabricatorController',
- 'PhabricatorFactCountEngine' => 'PhabricatorFactEngine',
'PhabricatorFactCursor' => 'PhabricatorFactDAO',
'PhabricatorFactDAO' => 'PhabricatorLiskDAO',
'PhabricatorFactDaemon' => 'PhabricatorDaemon',
+ 'PhabricatorFactDimension' => 'PhabricatorFactDAO',
'PhabricatorFactEngine' => 'Phobject',
'PhabricatorFactEngineTestCase' => 'PhabricatorTestCase',
'PhabricatorFactHomeController' => 'PhabricatorFactController',
- 'PhabricatorFactLastUpdatedEngine' => 'PhabricatorFactEngine',
+ 'PhabricatorFactIntDatapoint' => 'PhabricatorFactDAO',
+ 'PhabricatorFactKeyDimension' => 'PhabricatorFactDimension',
'PhabricatorFactManagementAnalyzeWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementCursorsWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementDestroyWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementListWorkflow' => 'PhabricatorFactManagementWorkflow',
- 'PhabricatorFactManagementStatusWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementWorkflow' => 'PhabricatorManagementWorkflow',
+ 'PhabricatorFactManiphestTaskEngine' => 'PhabricatorFactEngine',
+ 'PhabricatorFactObjectDimension' => 'PhabricatorFactDimension',
'PhabricatorFactRaw' => 'PhabricatorFactDAO',
- 'PhabricatorFactSimpleSpec' => 'PhabricatorFactSpec',
- 'PhabricatorFactSpec' => 'Phobject',
'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator',
'PhabricatorFavoritesApplication' => 'PhabricatorApplication',
'PhabricatorFavoritesController' => 'PhabricatorController',
@@ -9373,6 +9376,7 @@
'PhabricatorPirateEnglishTranslation' => 'PhutilTranslation',
'PhabricatorPlatformSite' => 'PhabricatorSite',
'PhabricatorPointsEditField' => 'PhabricatorEditField',
+ 'PhabricatorPointsFact' => 'PhabricatorFact',
'PhabricatorPolicies' => 'PhabricatorPolicyConstants',
'PhabricatorPolicy' => array(
'PhabricatorPolicyDAO',
diff --git a/src/applications/differential/application/PhabricatorDifferentialApplication.php b/src/applications/differential/application/PhabricatorDifferentialApplication.php
--- a/src/applications/differential/application/PhabricatorDifferentialApplication.php
+++ b/src/applications/differential/application/PhabricatorDifferentialApplication.php
@@ -35,12 +35,6 @@
);
}
- public function getFactObjectsForAnalysis() {
- return array(
- new DifferentialRevision(),
- );
- }
-
public function getTitleGlyph() {
return "\xE2\x9A\x99";
}
diff --git a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php
--- a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php
+++ b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php
@@ -39,12 +39,6 @@
);
}
- public function getFactObjectsForAnalysis() {
- return array(
- new PhabricatorRepositoryCommit(),
- );
- }
-
public function getRemarkupRules() {
return array(
new DiffusionCommitRemarkupRule(),
diff --git a/src/applications/fact/controller/PhabricatorFactChartController.php b/src/applications/fact/controller/PhabricatorFactChartController.php
--- a/src/applications/fact/controller/PhabricatorFactChartController.php
+++ b/src/applications/fact/controller/PhabricatorFactChartController.php
@@ -5,27 +5,32 @@
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
- $table = new PhabricatorFactRaw();
- $conn_r = $table->establishConnection('r');
- $table_name = $table->getTableName();
-
$series = $request->getStr('y1');
- $specs = PhabricatorFactSpec::newSpecsForFactTypes(
- PhabricatorFactEngine::loadAllEngines(),
- array($series));
- $spec = idx($specs, $series);
+ $facts = PhabricatorFact::getAllFacts();
+ $fact = idx($facts, $series);
+
+ if (!$fact) {
+ return new Aphront404Response();
+ }
+
+ $key_id = id(new PhabricatorFactKeyDimension())
+ ->newDimensionID($fact->getKey());
+
+ $table = $fact->newDatapoint();
+ $conn_r = $table->establishConnection('r');
+ $table_name = $table->getTableName();
$data = queryfx_all(
$conn_r,
- 'SELECT valueX, epoch FROM %T WHERE factType = %s ORDER BY epoch ASC',
+ 'SELECT value, epoch FROM %T WHERE keyID = %d ORDER BY epoch ASC',
$table_name,
- $series);
+ $key_id);
$points = array();
$sum = 0;
foreach ($data as $key => $row) {
- $sum += (int)$row['valueX'];
+ $sum += (int)$row['value'];
$points[(int)$row['epoch']] = $sum;
}
@@ -71,7 +76,7 @@
));
$box = id(new PHUIObjectBoxView())
- ->setHeaderText(pht('Count of %s', $spec->getName()))
+ ->setHeaderText(pht('Count of %s', $fact->getName()))
->appendChild($chart);
$crumbs = $this->buildApplicationCrumbs();
diff --git a/src/applications/fact/controller/PhabricatorFactHomeController.php b/src/applications/fact/controller/PhabricatorFactHomeController.php
--- a/src/applications/fact/controller/PhabricatorFactHomeController.php
+++ b/src/applications/fact/controller/PhabricatorFactHomeController.php
@@ -15,45 +15,6 @@
return id(new AphrontRedirectResponse())->setURI($uri);
}
- $types = array(
- '+N:*',
- '+N:DREV',
- 'updated',
- );
-
- $engines = PhabricatorFactEngine::loadAllEngines();
- $specs = PhabricatorFactSpec::newSpecsForFactTypes($engines, $types);
-
- $facts = id(new PhabricatorFactAggregate())->loadAllWhere(
- 'factType IN (%Ls)',
- $types);
-
- $rows = array();
- foreach ($facts as $fact) {
- $spec = $specs[$fact->getFactType()];
-
- $name = $spec->getName();
- $value = $spec->formatValueForDisplay($viewer, $fact->getValueX());
-
- $rows[] = array($name, $value);
- }
-
- $table = new AphrontTableView($rows);
- $table->setHeaders(
- array(
- pht('Fact'),
- pht('Value'),
- ));
- $table->setColumnClasses(
- array(
- 'wide',
- 'n',
- ));
-
- $panel = new PHUIObjectBoxView();
- $panel->setHeaderText(pht('Facts'));
- $panel->setTable($table);
-
$chart_form = $this->buildChartForm();
$crumbs = $this->buildApplicationCrumbs();
@@ -64,46 +25,18 @@
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
- ->appendChild(array(
- $chart_form,
- $panel,
- ));
-
+ ->appendChild(
+ array(
+ $chart_form,
+ ));
}
private function buildChartForm() {
$request = $this->getRequest();
$viewer = $request->getUser();
- $table = new PhabricatorFactRaw();
- $conn_r = $table->establishConnection('r');
- $table_name = $table->getTableName();
-
- $facts = queryfx_all(
- $conn_r,
- 'SELECT DISTINCT factType from %T',
- $table_name);
-
- $specs = PhabricatorFactSpec::newSpecsForFactTypes(
- PhabricatorFactEngine::loadAllEngines(),
- ipull($facts, 'factType'));
-
- $options = array();
- foreach ($specs as $spec) {
- if ($spec->getUnit() == PhabricatorFactSpec::UNIT_COUNT) {
- $options[$spec->getType()] = $spec->getName();
- }
- }
-
- if (!$options) {
- return id(new PHUIInfoView())
- ->setSeverity(PHUIInfoView::SEVERITY_NODATA)
- ->setTitle(pht('No Chartable Facts'))
- ->appendChild(phutil_tag(
- 'p',
- array(),
- pht('There are no facts that can be plotted yet.')));
- }
+ $specs = PhabricatorFact::getAllFacts();
+ $options = mpull($specs, 'getName', 'getKey');
$form = id(new AphrontFormView())
->setUser($viewer)
diff --git a/src/applications/fact/daemon/PhabricatorFactDaemon.php b/src/applications/fact/daemon/PhabricatorFactDaemon.php
--- a/src/applications/fact/daemon/PhabricatorFactDaemon.php
+++ b/src/applications/fact/daemon/PhabricatorFactDaemon.php
@@ -4,8 +4,6 @@
private $engines;
- const RAW_FACT_BUFFER_LIMIT = 128;
-
protected function run() {
$this->setEngines(PhabricatorFactEngine::loadAllEngines());
while (!$this->shouldExit()) {
@@ -15,7 +13,6 @@
foreach ($iterators as $iterator_name => $iterator) {
$this->processIteratorWithCursor($iterator_name, $iterator);
}
- $this->processAggregates();
$this->log(pht('Zzz...'));
$this->sleep(60 * 5);
@@ -72,59 +69,41 @@
public function processIterator($iterator) {
$result = null;
- $raw_facts = array();
+ $datapoints = array();
foreach ($iterator as $key => $object) {
$phid = $object->getPHID();
$this->log(pht('Processing %s...', $phid));
- $raw_facts[$phid] = $this->computeRawFacts($object);
- if (count($raw_facts) > self::RAW_FACT_BUFFER_LIMIT) {
- $this->updateRawFacts($raw_facts);
- $raw_facts = array();
+ $datapoints[$phid] = $this->newDatapoints($object);
+ if (count($datapoints) > 1024) {
+ $this->updateDatapoints($datapoints);
+ $datapoints = array();
}
$result = $key;
}
- if ($raw_facts) {
- $this->updateRawFacts($raw_facts);
- $raw_facts = array();
+ if ($datapoints) {
+ $this->updateDatapoints($datapoints);
+ $datapoints = array();
}
return $result;
}
- public function processAggregates() {
- $this->log(pht('Processing aggregates.'));
-
- $facts = $this->computeAggregateFacts();
- $this->updateAggregateFacts($facts);
- }
-
- private function computeAggregateFacts() {
+ private function newDatapoints(PhabricatorLiskDAO $object) {
$facts = array();
foreach ($this->engines as $engine) {
- if (!$engine->shouldComputeAggregateFacts()) {
+ if (!$engine->supportsDatapointsForObject($object)) {
continue;
}
- $facts[] = $engine->computeAggregateFacts();
- }
- return array_mergev($facts);
- }
-
- private function computeRawFacts(PhabricatorLiskDAO $object) {
- $facts = array();
- foreach ($this->engines as $engine) {
- if (!$engine->shouldComputeRawFactsForObject($object)) {
- continue;
- }
- $facts[] = $engine->computeRawFactsForObject($object);
+ $facts[] = $engine->newDatapointsForObject($object);
}
return array_mergev($facts);
}
- private function updateRawFacts(array $map) {
+ private function updateDatapoints(array $map) {
foreach ($map as $phid => $facts) {
- assert_instances_of($facts, 'PhabricatorFactRaw');
+ assert_instances_of($facts, 'PhabricatorFactIntDatapoint');
}
$phids = array_keys($map);
@@ -132,76 +111,79 @@
return;
}
- $table = new PhabricatorFactRaw();
+
+ $fact_keys = array();
+ $objects = array();
+ foreach ($map as $phid => $facts) {
+ foreach ($facts as $fact) {
+ $fact_keys[$fact->getKey()] = true;
+
+ $object_phid = $fact->getObjectPHID();
+ $objects[$object_phid] = $object_phid;
+
+ $dimension_phid = $fact->getDimensionPHID();
+ if ($dimension_phid !== null) {
+ $objects[$dimension_phid] = $dimension_phid;
+ }
+ }
+ }
+
+ $key_map = id(new PhabricatorFactKeyDimension())
+ ->newDimensionMap(array_keys($fact_keys));
+ $object_map = id(new PhabricatorFactObjectDimension())
+ ->newDimensionMap(array_keys($objects));
+
+ $table = new PhabricatorFactIntDatapoint();
$conn = $table->establishConnection('w');
$table_name = $table->getTableName();
$sql = array();
foreach ($map as $phid => $facts) {
foreach ($facts as $fact) {
+ $key_id = $key_map[$fact->getKey()];
+ $object_id = $object_map[$fact->getObjectPHID()];
+
+ $dimension_phid = $fact->getDimensionPHID();
+ if ($dimension_phid !== null) {
+ $dimension_id = $object_map[$dimension_phid];
+ } else {
+ $dimension_id = null;
+ }
+
$sql[] = qsprintf(
$conn,
- '(%s, %s, %s, %d, %d, %d)',
- $fact->getFactType(),
- $fact->getObjectPHID(),
- $fact->getObjectA(),
- $fact->getValueX(),
- $fact->getValueY(),
+ '(%d, %d, %nd, %d, %d)',
+ $key_id,
+ $object_id,
+ $dimension_id,
+ $fact->getValue(),
$fact->getEpoch());
}
}
+ $rebuilt_ids = array_select_keys($object_map, $phids);
+
$table->openTransaction();
queryfx(
$conn,
- 'DELETE FROM %T WHERE objectPHID IN (%Ls)',
+ 'DELETE FROM %T WHERE objectID IN (%Ld)',
$table_name,
- $phids);
+ $rebuilt_ids);
if ($sql) {
- foreach (array_chunk($sql, 256) as $chunk) {
+ foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) {
queryfx(
$conn,
'INSERT INTO %T
- (factType, objectPHID, objectA, valueX, valueY, epoch)
+ (keyID, objectID, dimensionID, value, epoch)
VALUES %Q',
$table_name,
- implode(', ', $chunk));
+ $chunk);
}
}
$table->saveTransaction();
}
- private function updateAggregateFacts(array $facts) {
- if (!$facts) {
- return;
- }
-
- $table = new PhabricatorFactAggregate();
- $conn = $table->establishConnection('w');
- $table_name = $table->getTableName();
-
- $sql = array();
- foreach ($facts as $fact) {
- $sql[] = qsprintf(
- $conn,
- '(%s, %s, %d)',
- $fact->getFactType(),
- $fact->getObjectPHID(),
- $fact->getValueX());
- }
-
- foreach (array_chunk($sql, 256) as $chunk) {
- queryfx(
- $conn,
- 'INSERT INTO %T (factType, objectPHID, valueX) VALUES %Q
- ON DUPLICATE KEY UPDATE valueX = VALUES(valueX)',
- $table_name,
- implode(', ', $chunk));
- }
-
- }
-
}
diff --git a/src/applications/fact/engine/PhabricatorFactCountEngine.php b/src/applications/fact/engine/PhabricatorFactCountEngine.php
deleted file mode 100644
--- a/src/applications/fact/engine/PhabricatorFactCountEngine.php
+++ /dev/null
@@ -1,86 +0,0 @@
-<?php
-
-/**
- * Simple fact engine which counts objects.
- */
-final class PhabricatorFactCountEngine extends PhabricatorFactEngine {
-
- public function getFactSpecs(array $fact_types) {
- $results = array();
- foreach ($fact_types as $type) {
- if (!strncmp($type, '+N:', 3)) {
- if ($type == '+N:*') {
- $name = pht('Total Objects');
- } else {
- $name = pht('Total Objects of type %s', substr($type, 3));
- }
-
- $results[] = id(new PhabricatorFactSimpleSpec($type))
- ->setName($name)
- ->setUnit(PhabricatorFactSimpleSpec::UNIT_COUNT);
- }
-
- if (!strncmp($type, 'N:', 2)) {
- if ($type == 'N:*') {
- $name = pht('Objects');
- } else {
- $name = pht('Objects of type %s', substr($type, 2));
- }
- $results[] = id(new PhabricatorFactSimpleSpec($type))
- ->setName($name)
- ->setUnit(PhabricatorFactSimpleSpec::UNIT_COUNT);
- }
-
- }
- return $results;
- }
-
- public function shouldComputeRawFactsForObject(PhabricatorLiskDAO $object) {
- return true;
- }
-
- public function computeRawFactsForObject(PhabricatorLiskDAO $object) {
- $facts = array();
-
- $phid = $object->getPHID();
- $type = phid_get_type($phid);
-
- foreach (array('N:*', 'N:'.$type) as $fact_type) {
- $facts[] = id(new PhabricatorFactRaw())
- ->setFactType($fact_type)
- ->setObjectPHID($phid)
- ->setValueX(1)
- ->setEpoch($object->getDateCreated());
- }
-
- return $facts;
- }
-
- public function shouldComputeAggregateFacts() {
- return true;
- }
-
- public function computeAggregateFacts() {
- $table = new PhabricatorFactRaw();
- $table_name = $table->getTableName();
- $conn = $table->establishConnection('r');
-
- $counts = queryfx_all(
- $conn,
- 'SELECT factType, SUM(valueX) N FROM %T WHERE factType LIKE %>
- GROUP BY factType',
- $table_name,
- 'N:');
-
- $facts = array();
- foreach ($counts as $count) {
- $facts[] = id(new PhabricatorFactAggregate())
- ->setFactType('+'.$count['factType'])
- ->setValueX($count['N']);
- }
-
- return $facts;
- }
-
-
-}
diff --git a/src/applications/fact/engine/PhabricatorFactEngine.php b/src/applications/fact/engine/PhabricatorFactEngine.php
--- a/src/applications/fact/engine/PhabricatorFactEngine.php
+++ b/src/applications/fact/engine/PhabricatorFactEngine.php
@@ -2,30 +2,37 @@
abstract class PhabricatorFactEngine extends Phobject {
+ private $factMap;
+
final public static function loadAllEngines() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->execute();
}
- public function getFactSpecs(array $fact_types) {
- return array();
- }
+ abstract public function newFacts();
- public function shouldComputeRawFactsForObject(PhabricatorLiskDAO $object) {
- return false;
- }
+ abstract public function supportsDatapointsForObject(
+ PhabricatorLiskDAO $object);
- public function computeRawFactsForObject(PhabricatorLiskDAO $object) {
- return array();
- }
+ abstract public function newDatapointsForObject(PhabricatorLiskDAO $object);
- public function shouldComputeAggregateFacts() {
- return false;
- }
+ final protected function getFact($key) {
+ if ($this->factMap === null) {
+ $facts = $this->newFacts();
+ $facts = mpull($facts, null, 'getKey');
+ $this->factMap = $facts;
+ }
+
+ if (!isset($this->factMap[$key])) {
+ throw new Exception(
+ pht(
+ 'Unknown fact ("%s") for engine "%s".',
+ $key,
+ get_class($this)));
+ }
- public function computeAggregateFacts() {
- return array();
+ return $this->factMap[$key];
}
}
diff --git a/src/applications/fact/engine/PhabricatorFactLastUpdatedEngine.php b/src/applications/fact/engine/PhabricatorFactLastUpdatedEngine.php
deleted file mode 100644
--- a/src/applications/fact/engine/PhabricatorFactLastUpdatedEngine.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-/**
- * Engine that records the time facts were last updated.
- */
-final class PhabricatorFactLastUpdatedEngine extends PhabricatorFactEngine {
-
- public function getFactSpecs(array $fact_types) {
- $results = array();
- foreach ($fact_types as $type) {
- if ($type == 'updated') {
- $results[] = id(new PhabricatorFactSimpleSpec($type))
- ->setName(pht('Facts Last Updated'))
- ->setUnit(PhabricatorFactSimpleSpec::UNIT_EPOCH);
- }
- }
- return $results;
- }
-
- public function shouldComputeAggregateFacts() {
- return true;
- }
-
- public function computeAggregateFacts() {
- $facts = array();
-
- $facts[] = id(new PhabricatorFactAggregate())
- ->setFactType('updated')
- ->setValueX(time());
-
- return $facts;
- }
-
-}
diff --git a/src/applications/fact/engine/PhabricatorFactManiphestTaskEngine.php b/src/applications/fact/engine/PhabricatorFactManiphestTaskEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/fact/engine/PhabricatorFactManiphestTaskEngine.php
@@ -0,0 +1,34 @@
+<?php
+
+final class PhabricatorFactManiphestTaskEngine
+ extends PhabricatorFactEngine {
+
+ public function newFacts() {
+ return array(
+ id(new PhabricatorPointsFact())
+ ->setKey('tasks.count.open'),
+ );
+ }
+
+ public function supportsDatapointsForObject(PhabricatorLiskDAO $object) {
+ return ($object instanceof ManiphestTask);
+ }
+
+ public function newDatapointsForObject(PhabricatorLiskDAO $object) {
+ $datapoints = array();
+
+ $phid = $object->getPHID();
+ $type = phid_get_type($phid);
+
+ $datapoint = $this->getFact('tasks.count.open')
+ ->newDatapoint();
+
+ $datapoints[] = $datapoint
+ ->setObjectPHID($phid)
+ ->setValue(1)
+ ->setEpoch($object->getDateCreated());
+
+ return $datapoints;
+ }
+
+}
diff --git a/src/applications/fact/fact/PhabricatorFact.php b/src/applications/fact/fact/PhabricatorFact.php
new file mode 100644
--- /dev/null
+++ b/src/applications/fact/fact/PhabricatorFact.php
@@ -0,0 +1,40 @@
+<?php
+
+abstract class PhabricatorFact extends Phobject {
+
+ private $key;
+
+ public static function getAllFacts() {
+ $engines = PhabricatorFactEngine::loadAllEngines();
+
+ $map = array();
+ foreach ($engines as $engine) {
+ $facts = $engine->newFacts();
+ $facts = mpull($facts, null, 'getKey');
+ $map += $facts;
+ }
+
+ return $map;
+ }
+
+ final public function setKey($key) {
+ $this->key = $key;
+ return $this;
+ }
+
+ final public function getKey() {
+ return $this->key;
+ }
+
+ final public function getName() {
+ return pht('Fact "%s"', $this->getKey());
+ }
+
+ final public function newDatapoint() {
+ return $this->newTemplateDatapoint()
+ ->setKey($this->getKey());
+ }
+
+ abstract protected function newTemplateDatapoint();
+
+}
diff --git a/src/applications/fact/fact/PhabricatorPointsFact.php b/src/applications/fact/fact/PhabricatorPointsFact.php
new file mode 100644
--- /dev/null
+++ b/src/applications/fact/fact/PhabricatorPointsFact.php
@@ -0,0 +1,9 @@
+<?php
+
+final class PhabricatorPointsFact extends PhabricatorFact {
+
+ protected function newTemplateDatapoint() {
+ return new PhabricatorFactIntDatapoint();
+ }
+
+}
diff --git a/src/applications/fact/management/PhabricatorFactManagementAnalyzeWorkflow.php b/src/applications/fact/management/PhabricatorFactManagementAnalyzeWorkflow.php
--- a/src/applications/fact/management/PhabricatorFactManagementAnalyzeWorkflow.php
+++ b/src/applications/fact/management/PhabricatorFactManagementAnalyzeWorkflow.php
@@ -58,10 +58,6 @@
}
}
- if (!$args->getArg('skip-aggregates')) {
- $daemon->processAggregates();
- }
-
return 0;
}
diff --git a/src/applications/fact/management/PhabricatorFactManagementDestroyWorkflow.php b/src/applications/fact/management/PhabricatorFactManagementDestroyWorkflow.php
--- a/src/applications/fact/management/PhabricatorFactManagementDestroyWorkflow.php
+++ b/src/applications/fact/management/PhabricatorFactManagementDestroyWorkflow.php
@@ -23,8 +23,13 @@
}
$tables = array();
- $tables[] = new PhabricatorFactRaw();
- $tables[] = new PhabricatorFactAggregate();
+ $tables[] = new PhabricatorFactCursor();
+
+ $tables[] = new PhabricatorFactIntDatapoint();
+
+ $tables[] = new PhabricatorFactObjectDimension();
+ $tables[] = new PhabricatorFactKeyDimension();
+
foreach ($tables as $table) {
$conn = $table->establishConnection('w');
$name = $table->getTableName();
diff --git a/src/applications/fact/management/PhabricatorFactManagementStatusWorkflow.php b/src/applications/fact/management/PhabricatorFactManagementStatusWorkflow.php
deleted file mode 100644
--- a/src/applications/fact/management/PhabricatorFactManagementStatusWorkflow.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-final class PhabricatorFactManagementStatusWorkflow
- extends PhabricatorFactManagementWorkflow {
-
- protected function didConstruct() {
- $this
- ->setName('status')
- ->setSynopsis(pht('Show status of fact data.'))
- ->setArguments(array());
- }
-
- public function execute(PhutilArgumentParser $args) {
- $console = PhutilConsole::getConsole();
-
- $map = array(
- 'raw' => new PhabricatorFactRaw(),
- 'agg' => new PhabricatorFactAggregate(),
- );
-
- foreach ($map as $type => $table) {
- $conn = $table->establishConnection('r');
- $name = $table->getTableName();
-
- $row = queryfx_one(
- $conn,
- 'SELECT COUNT(*) N FROM %T',
- $name);
-
- $n = $row['N'];
-
- switch ($type) {
- case 'raw':
- $desc = pht('There are %d raw fact(s) in storage.', $n);
- break;
- case 'agg':
- $desc = pht('There are %d aggregate fact(s) in storage.', $n);
- break;
- }
-
- $console->writeOut("%s\n", $desc);
- }
-
- return 0;
- }
-
-}
diff --git a/src/applications/fact/spec/PhabricatorFactSimpleSpec.php b/src/applications/fact/spec/PhabricatorFactSimpleSpec.php
deleted file mode 100644
--- a/src/applications/fact/spec/PhabricatorFactSimpleSpec.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-final class PhabricatorFactSimpleSpec extends PhabricatorFactSpec {
-
- private $type;
- private $name;
- private $unit;
-
- public function __construct($type) {
- $this->type = $type;
- }
-
- public function getType() {
- return $this->type;
- }
-
- public function setUnit($unit) {
- $this->unit = $unit;
- return $this;
- }
-
- public function getUnit() {
- return $this->unit;
- }
-
- public function setName($name) {
- $this->name = $name;
- return $this;
- }
-
- public function getName() {
- if ($this->name !== null) {
- return $this->name;
- }
- return parent::getName();
- }
-
-}
diff --git a/src/applications/fact/spec/PhabricatorFactSpec.php b/src/applications/fact/spec/PhabricatorFactSpec.php
deleted file mode 100644
--- a/src/applications/fact/spec/PhabricatorFactSpec.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-abstract class PhabricatorFactSpec extends Phobject {
-
- const UNIT_COUNT = 'unit-count';
- const UNIT_EPOCH = 'unit-epoch';
-
- public static function newSpecsForFactTypes(
- array $engines,
- array $fact_types) {
- assert_instances_of($engines, 'PhabricatorFactEngine');
-
- $map = array();
- foreach ($engines as $engine) {
- $specs = $engine->getFactSpecs($fact_types);
- $specs = mpull($specs, null, 'getType');
- $map += $specs;
- }
-
- foreach ($fact_types as $type) {
- if (empty($map[$type])) {
- $map[$type] = new PhabricatorFactSimpleSpec($type);
- }
- }
-
- return $map;
- }
-
- abstract public function getType();
-
- public function getUnit() {
- return null;
- }
-
- public function getName() {
- return pht(
- 'Fact (%s)',
- $this->getType());
- }
-
- public function formatValueForDisplay(PhabricatorUser $user, $value) {
- $unit = $this->getUnit();
- switch ($unit) {
- case self::UNIT_COUNT:
- return number_format($value);
- case self::UNIT_EPOCH:
- return phabricator_datetime($value, $user);
- default:
- return $value;
- }
- }
-
-}
diff --git a/src/applications/fact/storage/PhabricatorFactDimension.php b/src/applications/fact/storage/PhabricatorFactDimension.php
new file mode 100644
--- /dev/null
+++ b/src/applications/fact/storage/PhabricatorFactDimension.php
@@ -0,0 +1,85 @@
+<?php
+
+abstract class PhabricatorFactDimension extends PhabricatorFactDAO {
+
+ abstract protected function getDimensionColumnName();
+
+ final public function newDimensionID($key) {
+ $map = $this->newDimensionMap(array($key));
+ return $map[$key];
+ }
+
+ final public function newDimensionMap(array $keys) {
+ if (!$keys) {
+ return array();
+ }
+
+ $conn = $this->establishConnection('r');
+ $column = $this->getDimensionColumnName();
+
+ $rows = queryfx_all(
+ $conn,
+ 'SELECT id, %C FROM %T WHERE %C IN (%Ls)',
+ $column,
+ $this->getTableName(),
+ $column,
+ $keys);
+ $rows = ipull($rows, 'id', $column);
+
+ $map = array();
+ $need = array();
+ foreach ($keys as $key) {
+ if (isset($rows[$key])) {
+ $map[$key] = (int)$rows[$key];
+ } else {
+ $need[] = $key;
+ }
+ }
+
+ if (!$need) {
+ return $map;
+ }
+
+ $sql = array();
+ foreach ($need as $key) {
+ $sql[] = qsprintf(
+ $conn,
+ '(%s)',
+ $key);
+ }
+
+ foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) {
+ queryfx(
+ $conn,
+ 'INSERT IGNORE INTO %T (%C) VALUES %Q',
+ $this->getTableName(),
+ $column,
+ $chunk);
+ }
+
+ $rows = queryfx_all(
+ $conn,
+ 'SELECT id, %C FROM %T WHERE %C IN (%Ls)',
+ $column,
+ $this->getTableName(),
+ $column,
+ $need);
+ $rows = ipull($rows, 'id', $column);
+
+ foreach ($keys as $key) {
+ if (isset($rows[$key])) {
+ $map[$key] = (int)$rows[$key];
+ } else {
+ throw new Exception(
+ pht(
+ 'Failed to load or generate dimension ID ("%s") for dimension '.
+ 'key "%s".',
+ get_class($this),
+ $key));
+ }
+ }
+
+ return $map;
+ }
+
+}
diff --git a/src/applications/fact/storage/PhabricatorFactIntDatapoint.php b/src/applications/fact/storage/PhabricatorFactIntDatapoint.php
new file mode 100644
--- /dev/null
+++ b/src/applications/fact/storage/PhabricatorFactIntDatapoint.php
@@ -0,0 +1,61 @@
+<?php
+
+final class PhabricatorFactIntDatapoint extends PhabricatorFactDAO {
+
+ protected $keyID;
+ protected $objectID;
+ protected $dimensionID;
+ protected $value;
+ protected $epoch;
+
+ private $key;
+ private $objectPHID;
+ private $dimensionPHID;
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_TIMESTAMPS => false,
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'id' => 'auto64',
+ 'dimensionID' => 'id?',
+ 'value' => 'sint64',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_dimension' => array(
+ 'columns' => array('keyID', 'dimensionID'),
+ ),
+ 'key_object' => array(
+ 'columns' => array('objectID'),
+ ),
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function setKey($key) {
+ $this->key = $key;
+ return $this;
+ }
+
+ public function getKey() {
+ return $this->key;
+ }
+
+ public function setObjectPHID($object_phid) {
+ $this->objectPHID = $object_phid;
+ return $this;
+ }
+
+ public function getObjectPHID() {
+ return $this->objectPHID;
+ }
+
+ public function setDimensionPHID($dimension_phid) {
+ $this->dimensionPHID = $dimension_phid;
+ return $this;
+ }
+
+ public function getDimensionPHID() {
+ return $this->dimensionPHID;
+ }
+
+}
diff --git a/src/applications/fact/storage/PhabricatorFactKeyDimension.php b/src/applications/fact/storage/PhabricatorFactKeyDimension.php
new file mode 100644
--- /dev/null
+++ b/src/applications/fact/storage/PhabricatorFactKeyDimension.php
@@ -0,0 +1,27 @@
+<?php
+
+final class PhabricatorFactKeyDimension
+ extends PhabricatorFactDimension {
+
+ protected $factKey;
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_TIMESTAMPS => false,
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'factKey' => 'text64',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_factkey' => array(
+ 'columns' => array('factKey'),
+ 'unique' => true,
+ ),
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ protected function getDimensionColumnName() {
+ return 'factKey';
+ }
+
+}
diff --git a/src/applications/fact/storage/PhabricatorFactObjectDimension.php b/src/applications/fact/storage/PhabricatorFactObjectDimension.php
new file mode 100644
--- /dev/null
+++ b/src/applications/fact/storage/PhabricatorFactObjectDimension.php
@@ -0,0 +1,25 @@
+<?php
+
+final class PhabricatorFactObjectDimension
+ extends PhabricatorFactDimension {
+
+ protected $objectPHID;
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_TIMESTAMPS => false,
+ self::CONFIG_COLUMN_SCHEMA => array(),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_object' => array(
+ 'columns' => array('objectPHID'),
+ 'unique' => true,
+ ),
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ protected function getDimensionColumnName() {
+ return 'objectPHID';
+ }
+
+}
diff --git a/src/applications/ponder/application/PhabricatorPonderApplication.php b/src/applications/ponder/application/PhabricatorPonderApplication.php
--- a/src/applications/ponder/application/PhabricatorPonderApplication.php
+++ b/src/applications/ponder/application/PhabricatorPonderApplication.php
@@ -18,12 +18,6 @@
return 'fa-university';
}
- public function getFactObjectsForAnalysis() {
- return array(
- new PonderQuestion(),
- );
- }
-
public function getTitleGlyph() {
return "\xE2\x97\xB3";
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 23, 4:25 AM (20 h, 30 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7036077
Default Alt Text
D19119.id.diff (38 KB)
Attached To
Mode
D19119: Make Facts more modern, DRY, and dimensional
Attached
Detach File
Event Timeline
Log In to Comment