mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 00:42:41 +01:00
Add FactCursors and application fact datasources
Summary: - Add PhabricatorApplication. This is a general class that I have grand designs for, but used here to allow applications to provide objects for analysis by the facts appliction. - Add FactCursors, to keep track of where iterators are. - Make the daemon do something sort of useful. - Add `bin/fact cursors` for showing and managing objects and cursors. - Add some options to `bin/fact analyze`. Test Plan: - `bin/fact cursors`, `bin/fact cursors --reset DifferentialRevision`, `bin/fact cursors --reset X` - `bin/fact analyze`, `bin/fact analyze --all`, `bin/fact analyze --iterator DifferentialRevision --skip-aggregates` - `bin/phd debug fact` Reviewers: vrana, btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T1562 Differential Revision: https://secure.phabricator.com/D3098
This commit is contained in:
parent
c8578b9fa8
commit
f0af273165
10 changed files with 353 additions and 14 deletions
|
@ -36,6 +36,7 @@ $workflows = array(
|
|||
new PhabricatorFactManagementAnalyzeWorkflow(),
|
||||
new PhabricatorFactManagementStatusWorkflow(),
|
||||
new PhabricatorFactManagementListWorkflow(),
|
||||
new PhabricatorFactManagementCursorsWorkflow(),
|
||||
new PhutilHelpArgumentWorkflow(),
|
||||
);
|
||||
|
||||
|
|
|
@ -530,6 +530,9 @@ phutil_register_library_map(array(
|
|||
'PackageModifyMail' => 'applications/owners/mail/PackageModifyMail.php',
|
||||
'Phabricator404Controller' => 'applications/base/controller/Phabricator404Controller.php',
|
||||
'PhabricatorAccessLog' => 'infrastructure/PhabricatorAccessLog.php',
|
||||
'PhabricatorApplication' => 'applications/base/PhabricatorApplication.php',
|
||||
'PhabricatorApplicationDifferential' => 'applications/differential/application/PhabricatorApplicationDifferential.php',
|
||||
'PhabricatorApplicationManiphest' => 'applications/maniphest/application/PhabricatorApplicationManiphest.php',
|
||||
'PhabricatorAuditActionConstants' => 'applications/audit/constants/PhabricatorAuditActionConstants.php',
|
||||
'PhabricatorAuditAddCommentController' => 'applications/audit/controller/PhabricatorAuditAddCommentController.php',
|
||||
'PhabricatorAuditComment' => 'applications/audit/storage/PhabricatorAuditComment.php',
|
||||
|
@ -627,12 +630,14 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFactAggregate' => 'applications/fact/storage/PhabricatorFactAggregate.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',
|
||||
'PhabricatorFactEngine' => 'applications/fact/engine/PhabricatorFactEngine.php',
|
||||
'PhabricatorFactHomeController' => 'applications/fact/controller/PhabricatorFactHomeController.php',
|
||||
'PhabricatorFactLastUpdatedEngine' => 'applications/fact/engine/PhabricatorFactLastUpdatedEngine.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',
|
||||
|
@ -1579,6 +1584,8 @@ phutil_register_library_map(array(
|
|||
'PackageDeleteMail' => 'PackageMail',
|
||||
'PackageModifyMail' => 'PackageMail',
|
||||
'Phabricator404Controller' => 'PhabricatorController',
|
||||
'PhabricatorApplicationDifferential' => 'PhabricatorApplication',
|
||||
'PhabricatorApplicationManiphest' => 'PhabricatorApplication',
|
||||
'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController',
|
||||
'PhabricatorAuditComment' => 'PhabricatorAuditDAO',
|
||||
'PhabricatorAuditCommitListView' => 'AphrontView',
|
||||
|
@ -1669,16 +1676,19 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFactAggregate' => 'PhabricatorFactDAO',
|
||||
'PhabricatorFactController' => 'PhabricatorController',
|
||||
'PhabricatorFactCountEngine' => 'PhabricatorFactEngine',
|
||||
'PhabricatorFactCursor' => 'PhabricatorFactDAO',
|
||||
'PhabricatorFactDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorFactDaemon' => 'PhabricatorDaemon',
|
||||
'PhabricatorFactHomeController' => 'PhabricatorFactController',
|
||||
'PhabricatorFactLastUpdatedEngine' => 'PhabricatorFactEngine',
|
||||
'PhabricatorFactManagementAnalyzeWorkflow' => 'PhabricatorFactManagementWorkflow',
|
||||
'PhabricatorFactManagementCursorsWorkflow' => 'PhabricatorFactManagementWorkflow',
|
||||
'PhabricatorFactManagementDestroyWorkflow' => 'PhabricatorFactManagementWorkflow',
|
||||
'PhabricatorFactManagementListWorkflow' => 'PhabricatorFactManagementWorkflow',
|
||||
'PhabricatorFactManagementStatusWorkflow' => 'PhabricatorFactManagementWorkflow',
|
||||
'PhabricatorFactManagementWorkflow' => 'PhutilArgumentWorkflow',
|
||||
'PhabricatorFactRaw' => 'PhabricatorFactDAO',
|
||||
'PhabricatorFactSimpleSpec' => 'PhabricatorFactSpec',
|
||||
'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator',
|
||||
'PhabricatorFeedController' => 'PhabricatorController',
|
||||
'PhabricatorFeedDAO' => 'PhabricatorLiskDAO',
|
||||
|
|
70
src/applications/base/PhabricatorApplication.php
Normal file
70
src/applications/base/PhabricatorApplication.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @task info Application Information
|
||||
* @task fact Fact Integration
|
||||
* @task meta Application Management
|
||||
* @group apps
|
||||
*/
|
||||
abstract class PhabricatorApplication {
|
||||
|
||||
|
||||
/* -( Application Information )-------------------------------------------- */
|
||||
|
||||
|
||||
public function getName() {
|
||||
return substr(__CLASS__, strlen('PhabricatorApplication'));
|
||||
}
|
||||
|
||||
public function isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* -( Fact Integration )--------------------------------------------------- */
|
||||
|
||||
|
||||
public function getFactObjectsForAnalysis() {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
/* -( Application Management )--------------------------------------------- */
|
||||
|
||||
|
||||
public static function getAllInstalledApplications() {
|
||||
$classes = id(new PhutilSymbolLoader())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->setConcreteOnly(true)
|
||||
->selectAndLoadSymbols();
|
||||
|
||||
$apps = array();
|
||||
foreach ($classes as $class) {
|
||||
$app = newv($class['name'], array());
|
||||
if (!$app->isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
$apps[] = $app;
|
||||
}
|
||||
|
||||
return $apps;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorApplicationDifferential extends PhabricatorApplication {
|
||||
|
||||
public function getFactObjectsForAnalysis() {
|
||||
return array(
|
||||
new DifferentialRevision(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,7 +23,57 @@ final class PhabricatorFactDaemon extends PhabricatorDaemon {
|
|||
const RAW_FACT_BUFFER_LIMIT = 128;
|
||||
|
||||
public function run() {
|
||||
throw new Exception("This daemon doesn't do anything yet!");
|
||||
$this->setEngines(PhabricatorFactEngine::loadAllEngines());
|
||||
while (true) {
|
||||
$iterators = $this->getAllApplicationIterators();
|
||||
foreach ($iterators as $iterator_name => $iterator) {
|
||||
$this->processIteratorWithCursor($iterator_name, $iterator);
|
||||
}
|
||||
$this->processAggregates();
|
||||
|
||||
$this->log("Zzz...");
|
||||
$this->sleep(60 * 5);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getAllApplicationIterators() {
|
||||
$apps = PhabricatorApplication::getAllInstalledApplications();
|
||||
|
||||
$iterators = array();
|
||||
foreach ($apps as $app) {
|
||||
foreach ($app->getFactObjectsForAnalysis() as $object) {
|
||||
$iterator = new PhabricatorFactUpdateIterator($object);
|
||||
$iterators[get_class($object)] = $iterator;
|
||||
}
|
||||
}
|
||||
|
||||
return $iterators;
|
||||
}
|
||||
|
||||
public function processIteratorWithCursor($iterator_name, $iterator) {
|
||||
$this->log("Processing cursor '{$iterator_name}'.");
|
||||
|
||||
$cursor = id(new PhabricatorFactCursor())->loadOneWhere(
|
||||
'name = %s',
|
||||
$iterator_name);
|
||||
if (!$cursor) {
|
||||
$cursor = new PhabricatorFactCursor();
|
||||
$cursor->setName($iterator_name);
|
||||
$position = null;
|
||||
} else {
|
||||
$position = $cursor->getPosition();
|
||||
}
|
||||
|
||||
if ($position) {
|
||||
$iterator->setPosition($position);
|
||||
}
|
||||
|
||||
$new_cursor_position = $this->processIterator($iterator);
|
||||
|
||||
if ($new_cursor_position) {
|
||||
$cursor->setPosition($new_cursor_position);
|
||||
$cursor->save();
|
||||
}
|
||||
}
|
||||
|
||||
public function setEngines(array $engines) {
|
||||
|
@ -38,7 +88,9 @@ final class PhabricatorFactDaemon extends PhabricatorDaemon {
|
|||
|
||||
$raw_facts = array();
|
||||
foreach ($iterator as $key => $object) {
|
||||
$raw_facts[$object->getPHID()] = $this->computeRawFacts($object);
|
||||
$phid = $object->getPHID();
|
||||
$this->log("Processing {$phid}...");
|
||||
$raw_facts[$phid] = $this->computeRawFacts($object);
|
||||
if (count($raw_facts) > self::RAW_FACT_BUFFER_LIMIT) {
|
||||
$this->updateRawFacts($raw_facts);
|
||||
$raw_facts = array();
|
||||
|
@ -55,6 +107,8 @@ final class PhabricatorFactDaemon extends PhabricatorDaemon {
|
|||
}
|
||||
|
||||
public function processAggregates() {
|
||||
$this->log("Processing aggregates.");
|
||||
|
||||
$facts = $this->computeAggregateFacts();
|
||||
$this->updateAggregateFacts($facts);
|
||||
}
|
||||
|
|
|
@ -28,12 +28,14 @@ final class PhabricatorFactUpdateIterator extends PhutilBufferedIterator {
|
|||
private $start;
|
||||
private $ignoreUpdatesDuration = 15;
|
||||
|
||||
public function __construct(LiskDAO $object, $start = null) {
|
||||
if ($start === null) {
|
||||
$start = '0:0';
|
||||
}
|
||||
public function __construct(LiskDAO $object) {
|
||||
$this->object = $object;
|
||||
$this->start = $start;
|
||||
$this->start = '0:0';
|
||||
}
|
||||
|
||||
public function setPosition($position) {
|
||||
$this->start = $position;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function didRewind() {
|
||||
|
|
|
@ -23,7 +23,23 @@ final class PhabricatorFactManagementAnalyzeWorkflow
|
|||
$this
|
||||
->setName('analyze')
|
||||
->setSynopsis(pht('Manually invoke fact analyzers.'))
|
||||
->setArguments(array());
|
||||
->setArguments(
|
||||
array(
|
||||
array(
|
||||
'name' => 'iterator',
|
||||
'param' => 'name',
|
||||
'repeat' => true,
|
||||
'help' => 'Process only __iterator__.',
|
||||
),
|
||||
array(
|
||||
'name' => 'all',
|
||||
'help' => 'Analyze from the beginning, ignoring cursors.',
|
||||
),
|
||||
array(
|
||||
'name' => 'skip-aggregates',
|
||||
'help' => 'Skip analysis of aggreate facts.',
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
public function execute(PhutilArgumentParser $args) {
|
||||
|
@ -33,15 +49,34 @@ final class PhabricatorFactManagementAnalyzeWorkflow
|
|||
$daemon->setVerbose(true);
|
||||
$daemon->setEngines(PhabricatorFactEngine::loadAllEngines());
|
||||
|
||||
$iterators = array(
|
||||
new PhabricatorFactUpdateIterator(new DifferentialRevision()),
|
||||
);
|
||||
$iterators = PhabricatorFactDaemon::getAllApplicationIterators();
|
||||
|
||||
foreach ($iterators as $iterator) {
|
||||
$daemon->processIterator($iterator);
|
||||
$selected = $args->getArg('iterator');
|
||||
if ($selected) {
|
||||
$use = array();
|
||||
foreach ($selected as $iterator_name) {
|
||||
if (isset($iterators[$iterator_name])) {
|
||||
$use[$iterator_name] = $iterators[$iterator_name];
|
||||
} else {
|
||||
$console->writeErr(
|
||||
"%s\n",
|
||||
pht("Iterator '%s' does not exist.", $iterator_name));
|
||||
}
|
||||
}
|
||||
$iterators = $use;
|
||||
}
|
||||
|
||||
$daemon->processAggregates();
|
||||
foreach ($iterators as $iterator_name => $iterator) {
|
||||
if ($args->getArg('all')) {
|
||||
$daemon->processIterator($iterator);
|
||||
} else {
|
||||
$daemon->processIteratorWithCursor($iterator_name, $iterator);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$args->getArg('skip-aggregates')) {
|
||||
$daemon->processAggregates();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorFactManagementCursorsWorkflow
|
||||
extends PhabricatorFactManagementWorkflow {
|
||||
|
||||
public function didConstruct() {
|
||||
$this
|
||||
->setName('cursors')
|
||||
->setSynopsis(pht('Show a list of fact iterators and cursors.'))
|
||||
->setExamples(
|
||||
"**cursors**\n".
|
||||
"**cursors** --reset __cursor__")
|
||||
->setArguments(
|
||||
array(
|
||||
array(
|
||||
'name' => 'reset',
|
||||
'param' => 'cursor',
|
||||
'repeat' => true,
|
||||
'help' => 'Reset cursor __cursor__.',
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
public function execute(PhutilArgumentParser $args) {
|
||||
$console = PhutilConsole::getConsole();
|
||||
|
||||
$reset = $args->getArg('reset');
|
||||
if ($reset) {
|
||||
foreach ($reset as $name) {
|
||||
$cursor = id(new PhabricatorFactCursor())->loadOneWhere(
|
||||
'name = %s',
|
||||
$name);
|
||||
if ($cursor) {
|
||||
$console->writeOut("%s\n", pht("Resetting cursor %s...", $name));
|
||||
$cursor->delete();
|
||||
} else {
|
||||
$console->writeErr(
|
||||
"%s\n",
|
||||
pht("Cursor %s does not exist or is already reset.", $name));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
$iterator_map = PhabricatorFactDaemon::getAllApplicationIterators();
|
||||
if (!$iterator_map) {
|
||||
$console->writeErr("%s\n", pht("No cursors."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
$cursors = id(new PhabricatorFactCursor())->loadAllWhere(
|
||||
'name IN (%Ls)',
|
||||
array_keys($iterator_map));
|
||||
$cursors = mpull($cursors, 'getPosition', 'getName');
|
||||
|
||||
foreach ($iterator_map as $iterator_name => $iterator) {
|
||||
$console->writeOut(
|
||||
"%s (%s)\n",
|
||||
$iterator_name,
|
||||
idx($cursors, $iterator_name, 'start'));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
25
src/applications/fact/storage/PhabricatorFactCursor.php
Normal file
25
src/applications/fact/storage/PhabricatorFactCursor.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorFactCursor extends PhabricatorFactDAO {
|
||||
|
||||
protected $id;
|
||||
protected $name;
|
||||
protected $position;
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorApplicationManiphest extends PhabricatorApplication {
|
||||
|
||||
public function isEnabled() {
|
||||
return PhabricatorEnv::getEnvConfig('maniphest.enabled');
|
||||
}
|
||||
|
||||
public function getFactObjectsForAnalysis() {
|
||||
return array(
|
||||
new ManiphestTask(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in a new issue