mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-18 10:41:08 +01:00
Add Nuance daemons and item types
Summary: Ref T10537. This adds an update daemon for pulling item data (e.g., figuring out who the author of a GitHub comment is) and routing items (e.g., sending them to a queue or applying them directly to a task). Also adds `bin/nuance update --item X` for doing this manually for debugging. And adds item types, for specializing item behavior. Previously, sources completely dictated item behavior, but I think we want something a little more flexible. Test Plan: - This still does nothing. - Ran `bin/nuance update --item 15`. - Saw an item route to a default queue. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10537 Differential Revision: https://secure.phabricator.com/D15441
This commit is contained in:
parent
3d44a5c253
commit
e5f867e0df
11 changed files with 259 additions and 10 deletions
|
@ -1420,6 +1420,7 @@ phutil_register_library_map(array(
|
|||
'NuanceConsoleController' => 'applications/nuance/controller/NuanceConsoleController.php',
|
||||
'NuanceController' => 'applications/nuance/controller/NuanceController.php',
|
||||
'NuanceDAO' => 'applications/nuance/storage/NuanceDAO.php',
|
||||
'NuanceGitHubEventItemType' => 'applications/nuance/item/NuanceGitHubEventItemType.php',
|
||||
'NuanceGitHubRepositoryImportCursor' => 'applications/nuance/cursor/NuanceGitHubRepositoryImportCursor.php',
|
||||
'NuanceGitHubRepositorySourceDefinition' => 'applications/nuance/source/NuanceGitHubRepositorySourceDefinition.php',
|
||||
'NuanceImportCursor' => 'applications/nuance/cursor/NuanceImportCursor.php',
|
||||
|
@ -1437,8 +1438,11 @@ phutil_register_library_map(array(
|
|||
'NuanceItemTransaction' => 'applications/nuance/storage/NuanceItemTransaction.php',
|
||||
'NuanceItemTransactionComment' => 'applications/nuance/storage/NuanceItemTransactionComment.php',
|
||||
'NuanceItemTransactionQuery' => 'applications/nuance/query/NuanceItemTransactionQuery.php',
|
||||
'NuanceItemType' => 'applications/nuance/item/NuanceItemType.php',
|
||||
'NuanceItemUpdateWorker' => 'applications/nuance/worker/NuanceItemUpdateWorker.php',
|
||||
'NuanceItemViewController' => 'applications/nuance/controller/NuanceItemViewController.php',
|
||||
'NuanceManagementImportWorkflow' => 'applications/nuance/management/NuanceManagementImportWorkflow.php',
|
||||
'NuanceManagementUpdateWorkflow' => 'applications/nuance/management/NuanceManagementUpdateWorkflow.php',
|
||||
'NuanceManagementWorkflow' => 'applications/nuance/management/NuanceManagementWorkflow.php',
|
||||
'NuancePhabricatorFormSourceDefinition' => 'applications/nuance/source/NuancePhabricatorFormSourceDefinition.php',
|
||||
'NuanceQuery' => 'applications/nuance/query/NuanceQuery.php',
|
||||
|
@ -1488,6 +1492,7 @@ phutil_register_library_map(array(
|
|||
'NuanceSourceTransactionQuery' => 'applications/nuance/query/NuanceSourceTransactionQuery.php',
|
||||
'NuanceSourceViewController' => 'applications/nuance/controller/NuanceSourceViewController.php',
|
||||
'NuanceTransaction' => 'applications/nuance/storage/NuanceTransaction.php',
|
||||
'NuanceWorker' => 'applications/nuance/worker/NuanceWorker.php',
|
||||
'OwnersConduitAPIMethod' => 'applications/owners/conduit/OwnersConduitAPIMethod.php',
|
||||
'OwnersEditConduitAPIMethod' => 'applications/owners/conduit/OwnersEditConduitAPIMethod.php',
|
||||
'OwnersPackageReplyHandler' => 'applications/owners/mail/OwnersPackageReplyHandler.php',
|
||||
|
@ -5671,6 +5676,7 @@ phutil_register_library_map(array(
|
|||
'NuanceConsoleController' => 'NuanceController',
|
||||
'NuanceController' => 'PhabricatorController',
|
||||
'NuanceDAO' => 'PhabricatorLiskDAO',
|
||||
'NuanceGitHubEventItemType' => 'NuanceItemType',
|
||||
'NuanceGitHubRepositoryImportCursor' => 'NuanceImportCursor',
|
||||
'NuanceGitHubRepositorySourceDefinition' => 'NuanceSourceDefinition',
|
||||
'NuanceImportCursor' => 'Phobject',
|
||||
|
@ -5695,8 +5701,11 @@ phutil_register_library_map(array(
|
|||
'NuanceItemTransaction' => 'NuanceTransaction',
|
||||
'NuanceItemTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
||||
'NuanceItemTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'NuanceItemType' => 'Phobject',
|
||||
'NuanceItemUpdateWorker' => 'NuanceWorker',
|
||||
'NuanceItemViewController' => 'NuanceController',
|
||||
'NuanceManagementImportWorkflow' => 'NuanceManagementWorkflow',
|
||||
'NuanceManagementUpdateWorkflow' => 'NuanceManagementWorkflow',
|
||||
'NuanceManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'NuancePhabricatorFormSourceDefinition' => 'NuanceSourceDefinition',
|
||||
'NuanceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
|
@ -5759,6 +5768,7 @@ phutil_register_library_map(array(
|
|||
'NuanceSourceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'NuanceSourceViewController' => 'NuanceSourceController',
|
||||
'NuanceTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'NuanceWorker' => 'PhabricatorWorker',
|
||||
'OwnersConduitAPIMethod' => 'ConduitAPIMethod',
|
||||
'OwnersEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
|
||||
'OwnersPackageReplyHandler' => 'PhabricatorMailReplyHandler',
|
||||
|
|
|
@ -166,14 +166,7 @@ final class NuanceGitHubRepositoryImportCursor
|
|||
$source->saveTransaction();
|
||||
|
||||
foreach ($new_items as $new_item) {
|
||||
PhabricatorWorker::scheduleTask(
|
||||
'NuanceImportWorker',
|
||||
array(
|
||||
'itemPHID' => $new_item->getPHID(),
|
||||
),
|
||||
array(
|
||||
'objectPHID' => $new_item->getPHID(),
|
||||
));
|
||||
$new_item->scheduleUpdate();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -256,7 +249,7 @@ final class NuanceGitHubRepositoryImportCursor
|
|||
return NuanceItem::initializeNewItem()
|
||||
->setStatus(NuanceItem::STATUS_IMPORTING)
|
||||
->setSourcePHID($source->getPHID())
|
||||
->setItemType('github.event')
|
||||
->setItemType(NuanceGitHubEventItemType::ITEMTYPE)
|
||||
->setItemKey($item_key)
|
||||
->setItemContainerKey($container_key)
|
||||
->setItemProperty('api.raw', $record);
|
||||
|
|
22
src/applications/nuance/item/NuanceGitHubEventItemType.php
Normal file
22
src/applications/nuance/item/NuanceGitHubEventItemType.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class NuanceGitHubEventItemType
|
||||
extends NuanceItemType {
|
||||
|
||||
const ITEMTYPE = 'github.event';
|
||||
|
||||
public function canUpdateItems() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function updateItemFromSource(NuanceItem $item) {
|
||||
// TODO: Link up the requestor, etc.
|
||||
|
||||
if ($item->getStatus() == NuanceItem::STATUS_IMPORTING) {
|
||||
$item
|
||||
->setStatus(NuanceItem::STATUS_ROUTING)
|
||||
->save();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
37
src/applications/nuance/item/NuanceItemType.php
Normal file
37
src/applications/nuance/item/NuanceItemType.php
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
abstract class NuanceItemType
|
||||
extends Phobject {
|
||||
|
||||
public function canUpdateItems() {
|
||||
return false;
|
||||
}
|
||||
|
||||
final public function updateItem(NuanceItem $item) {
|
||||
if (!$this->canUpdateItems()) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'This item type ("%s", of class "%s") can not update items.',
|
||||
$this->getItemTypeConstant(),
|
||||
get_class($this)));
|
||||
}
|
||||
|
||||
$this->updateItemFromSource($item);
|
||||
}
|
||||
|
||||
protected function updateItemFromSource(NuanceItem $item) {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
final public function getItemTypeConstant() {
|
||||
return $this->getPhobjectClassConstant('ITEMTYPE', 64);
|
||||
}
|
||||
|
||||
final public static function getAllItemTypes() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->setUniqueMethod('getItemTypeConstant')
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@ final class NuanceManagementImportWorkflow
|
|||
protected function didConstruct() {
|
||||
$this
|
||||
->setName('import')
|
||||
->setExamples('**import** [__options__]')
|
||||
->setExamples('**import** --source __source__ [__options__]')
|
||||
->setSynopsis(pht('Import data from a source.'))
|
||||
->setArguments(
|
||||
array(
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
final class NuanceManagementUpdateWorkflow
|
||||
extends NuanceManagementWorkflow {
|
||||
|
||||
protected function didConstruct() {
|
||||
$this
|
||||
->setName('update')
|
||||
->setExamples('**update** --item __item__ [__options__]')
|
||||
->setSynopsis(pht('Update or route an item.'))
|
||||
->setArguments(
|
||||
array(
|
||||
array(
|
||||
'name' => 'item',
|
||||
'param' => 'item',
|
||||
'help' => pht('Choose which item to route.'),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
public function execute(PhutilArgumentParser $args) {
|
||||
$item = $this->loadItem($args, 'item');
|
||||
|
||||
PhabricatorWorker::setRunAllTasksInProcess(true);
|
||||
$item->scheduleUpdate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -64,4 +64,54 @@ abstract class NuanceManagementWorkflow
|
|||
return head($sources);
|
||||
}
|
||||
|
||||
protected function loadITem(PhutilArgumentParser $argv, $key) {
|
||||
$item = $argv->getArg($key);
|
||||
if (!strlen($item)) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Specify a item with %s.',
|
||||
'--'.$key));
|
||||
}
|
||||
|
||||
$query = id(new NuanceItemQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->setRaisePolicyExceptions(true);
|
||||
|
||||
$type_unknown = PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN;
|
||||
|
||||
if (ctype_digit($item)) {
|
||||
$kind = 'id';
|
||||
$query->withIDs(array($item));
|
||||
} else if (phid_get_type($item) !== $type_unknown) {
|
||||
$kind = 'phid';
|
||||
$query->withPHIDs($item);
|
||||
} else {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Specify the ID or PHID of an item to update. Parameter "%s" '.
|
||||
'is not an ID or PHID.',
|
||||
$item));
|
||||
}
|
||||
|
||||
$items = $query->execute();
|
||||
|
||||
if (!$items) {
|
||||
switch ($kind) {
|
||||
case 'id':
|
||||
$message = pht(
|
||||
'No item exists with ID "%s".',
|
||||
$item);
|
||||
break;
|
||||
case 'phid':
|
||||
$message = pht(
|
||||
'No item exists with PHID "%s".',
|
||||
$item);
|
||||
break;
|
||||
}
|
||||
|
||||
throw new PhutilArgumentUsageException($message);
|
||||
}
|
||||
|
||||
return head($items);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,17 @@ final class NuanceItemQuery
|
|||
$item->attachSource($source);
|
||||
}
|
||||
|
||||
$type_map = NuanceItemType::getAllItemTypes();
|
||||
foreach ($items as $key => $item) {
|
||||
$type = idx($type_map, $item->getItemType());
|
||||
if (!$type) {
|
||||
$this->didRejectResult($items[$key]);
|
||||
unset($items[$key]);
|
||||
continue;
|
||||
}
|
||||
$item->attachImplementation($type);
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ final class NuanceItem
|
|||
PhabricatorApplicationTransactionInterface {
|
||||
|
||||
const STATUS_IMPORTING = 'importing';
|
||||
const STATUS_ROUTING = 'routing';
|
||||
const STATUS_OPEN = 'open';
|
||||
const STATUS_ASSIGNED = 'assigned';
|
||||
const STATUS_CLOSED = 'closed';
|
||||
|
@ -23,6 +24,7 @@ final class NuanceItem
|
|||
protected $mailKey;
|
||||
|
||||
private $source = self::ATTACHABLE;
|
||||
private $implementation = self::ATTACHABLE;
|
||||
|
||||
public static function initializeNewItem() {
|
||||
return id(new NuanceItem())
|
||||
|
@ -145,6 +147,26 @@ final class NuanceItem
|
|||
return pht('An Item');
|
||||
}
|
||||
|
||||
public function scheduleUpdate() {
|
||||
PhabricatorWorker::scheduleTask(
|
||||
'NuanceItemUpdateWorker',
|
||||
array(
|
||||
'itemPHID' => $this->getPHID(),
|
||||
),
|
||||
array(
|
||||
'objectPHID' => $this->getPHID(),
|
||||
));
|
||||
}
|
||||
|
||||
public function getImplementation() {
|
||||
return $this->assertAttached($this->implementation);
|
||||
}
|
||||
|
||||
public function attachImplementation(NuanceItemType $type) {
|
||||
$this->implementation = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||
|
||||
|
|
49
src/applications/nuance/worker/NuanceItemUpdateWorker.php
Normal file
49
src/applications/nuance/worker/NuanceItemUpdateWorker.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
final class NuanceItemUpdateWorker
|
||||
extends NuanceWorker {
|
||||
|
||||
protected function doWork() {
|
||||
$item_phid = $this->getTaskDataValue('itemPHID');
|
||||
|
||||
$hash = PhabricatorHash::digestForIndex($item_phid);
|
||||
$lock_key = "nuance.item.{$hash}";
|
||||
$lock = PhabricatorGlobalLock::newLock($lock_key);
|
||||
|
||||
$lock->lock(1);
|
||||
try {
|
||||
$item = $this->loadItem($item_phid);
|
||||
$this->updateItem($item);
|
||||
$this->routeItem($item);
|
||||
} catch (Exception $ex) {
|
||||
$lock->unlock();
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
$lock->unlock();
|
||||
}
|
||||
|
||||
private function updateItem(NuanceItem $item) {
|
||||
$impl = $item->getImplementation();
|
||||
if ($impl->canUpdateItems()) {
|
||||
$impl->updateItem($item);
|
||||
}
|
||||
}
|
||||
|
||||
private function routeItem(NuanceItem $item) {
|
||||
$status = $item->getStatus();
|
||||
if ($status != NuanceItem::STATUS_ROUTING) {
|
||||
return;
|
||||
}
|
||||
|
||||
$source = $item->getSource();
|
||||
|
||||
// For now, always route items into the source's default queue.
|
||||
|
||||
$item
|
||||
->setQueuePHID($source->getDefaultQueuePHID())
|
||||
->setStatus(NuanceItem::STATUS_OPEN)
|
||||
->save();
|
||||
}
|
||||
|
||||
}
|
25
src/applications/nuance/worker/NuanceWorker.php
Normal file
25
src/applications/nuance/worker/NuanceWorker.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
abstract class NuanceWorker extends PhabricatorWorker {
|
||||
|
||||
protected function getViewer() {
|
||||
return PhabricatorUser::getOmnipotentUser();
|
||||
}
|
||||
|
||||
protected function loadItem($item_phid) {
|
||||
$item = id(new NuanceItemQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs(array($item_phid))
|
||||
->executeOne();
|
||||
|
||||
if (!$item) {
|
||||
throw new PhabricatorWorkerPermanentFailureException(
|
||||
pht(
|
||||
'There is no Nuance item with PHID "%s".',
|
||||
$item_phid));
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue