1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 16:52:41 +01:00

Modernize Drydock CLI management of task execution

Summary:
Ref T2015. Currently, Drydock has a `wait-for-lease` workflow which is invoked in the background by the `lease` workflow.

The goal of this mechanism is to allow `bin/drydock lease` to print out logs as the lease is acquired. However, this predates the `runAllTasksInProcess` flags, and they provide a simpler and more robust way (potentially with `--trace` and `PhutilConsole`) to do synchronous execution and debug logging.

Simplify this whole mechanism: just run everything in-process in `bin/drydock lease`, and do logging via `--trace`. We could thread a `PhutilConsole` through things too, but this seems good enough for now.

Also various cleanup/etc.

Test Plan: Ran `bin/drydock lease`. Ran `bin/harbormaster build X --plan Y`, for `Y` being a Drydock-dependent build plan.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2015

Differential Revision: https://secure.phabricator.com/D7835
This commit is contained in:
epriestley 2013-12-27 13:15:12 -08:00
parent 536c606dde
commit 1650874004
9 changed files with 59 additions and 97 deletions

View file

@ -15,7 +15,6 @@ EOSYNOPSIS
$args->parseStandardArguments(); $args->parseStandardArguments();
$workflows = array( $workflows = array(
new DrydockManagementWaitForLeaseWorkflow(),
new DrydockManagementLeaseWorkflow(), new DrydockManagementLeaseWorkflow(),
new DrydockManagementCloseWorkflow(), new DrydockManagementCloseWorkflow(),
new DrydockManagementReleaseWorkflow(), new DrydockManagementReleaseWorkflow(),

View file

@ -671,7 +671,6 @@ phutil_register_library_map(array(
'DrydockManagementCreateResourceWorkflow' => 'applications/drydock/management/DrydockManagementCreateResourceWorkflow.php', 'DrydockManagementCreateResourceWorkflow' => 'applications/drydock/management/DrydockManagementCreateResourceWorkflow.php',
'DrydockManagementLeaseWorkflow' => 'applications/drydock/management/DrydockManagementLeaseWorkflow.php', 'DrydockManagementLeaseWorkflow' => 'applications/drydock/management/DrydockManagementLeaseWorkflow.php',
'DrydockManagementReleaseWorkflow' => 'applications/drydock/management/DrydockManagementReleaseWorkflow.php', 'DrydockManagementReleaseWorkflow' => 'applications/drydock/management/DrydockManagementReleaseWorkflow.php',
'DrydockManagementWaitForLeaseWorkflow' => 'applications/drydock/management/DrydockManagementWaitForLeaseWorkflow.php',
'DrydockManagementWorkflow' => 'applications/drydock/management/DrydockManagementWorkflow.php', 'DrydockManagementWorkflow' => 'applications/drydock/management/DrydockManagementWorkflow.php',
'DrydockPHIDTypeBlueprint' => 'applications/drydock/phid/DrydockPHIDTypeBlueprint.php', 'DrydockPHIDTypeBlueprint' => 'applications/drydock/phid/DrydockPHIDTypeBlueprint.php',
'DrydockPHIDTypeLease' => 'applications/drydock/phid/DrydockPHIDTypeLease.php', 'DrydockPHIDTypeLease' => 'applications/drydock/phid/DrydockPHIDTypeLease.php',
@ -3099,7 +3098,6 @@ phutil_register_library_map(array(
'DrydockManagementCreateResourceWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementCreateResourceWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementLeaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementLeaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementReleaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementReleaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementWaitForLeaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementWorkflow' => 'PhutilArgumentWorkflow', 'DrydockManagementWorkflow' => 'PhutilArgumentWorkflow',
'DrydockPHIDTypeBlueprint' => 'PhabricatorPHIDType', 'DrydockPHIDTypeBlueprint' => 'PhabricatorPHIDType',
'DrydockPHIDTypeLease' => 'PhabricatorPHIDType', 'DrydockPHIDTypeLease' => 'PhabricatorPHIDType',

View file

@ -53,4 +53,14 @@ final class DrydockBlueprintListController extends DrydockBlueprintController
return $view; return $view;
} }
public function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('New Blueprint'))
->setHref($this->getApplicationURI('/blueprint/create/'))
->setIcon('create'));
return $crumbs;
}
} }

View file

@ -38,38 +38,16 @@ final class DrydockManagementLeaseWorkflow
$attributes = $options->parse($attributes); $attributes = $options->parse($attributes);
} }
$lease = new DrydockLease(); PhabricatorWorker::setRunAllTasksInProcess(true);
$lease->setResourceType($resource_type);
$lease = id(new DrydockLease())
->setResourceType($resource_type);
if ($attributes) { if ($attributes) {
$lease->setAttributes($attributes); $lease->setAttributes($attributes);
} }
$lease->queueForActivation(); $lease
->queueForActivation()
$root = dirname(phutil_get_library_root('phabricator')); ->waitUntilActive();
$wait = new ExecFuture(
'php -f %s wait-for-lease --id %s',
$root.'/scripts/drydock/drydock_control.php',
$lease->getID());
$cursor = 0;
foreach (Futures(array($wait))->setUpdateInterval(1) as $key => $future) {
if ($future) {
$future->resolvex();
break;
}
$logs = id(new DrydockLogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withLeaseIDs(array($lease->getID()))
->execute();
if ($logs) {
foreach ($logs as $log) {
$console->writeErr("%s\n", $log->getMessage());
}
$cursor = max(mpull($logs, 'getID'));
}
}
$console->writeOut("Acquired Lease %s\n", $lease->getID()); $console->writeOut("Acquired Lease %s\n", $lease->getID());
return 0; return 0;

View file

@ -1,40 +0,0 @@
<?php
final class DrydockManagementWaitForLeaseWorkflow
extends DrydockManagementWorkflow {
public function didConstruct() {
$this
->setName('wait-for-lease')
->setSynopsis('Wait for a lease to become available.')
->setArguments(
array(
array(
'name' => 'id',
'param' => 'lease_id',
'help' => 'Lease ID to wait for.',
),
));
}
public function execute(PhutilArgumentParser $args) {
$lease_id = $args->getArg('id');
if (!$lease_id) {
throw new PhutilArgumentUsageException(
"Specify a lease ID with `--id`.");
}
$console = PhutilConsole::getConsole();
$lease = id(new DrydockLease())->load($lease_id);
if (!$lease) {
$console->writeErr("No such lease.\n");
return 1;
} else {
$lease->waitUntilActive();
$console->writeErr("Lease active.\n");
return 0;
}
}
}

View file

@ -40,10 +40,6 @@ final class DrydockLogQuery extends PhabricatorCursorPagedPolicyAwareQuery {
foreach ($logs as $key => $log) { foreach ($logs as $key => $log) {
$resource = idx($resources, $log->getResourceID()); $resource = idx($resources, $log->getResourceID());
if (!$resource) {
unset($logs[$key]);
continue;
}
$log->attachResource($resource); $log->attachResource($resource);
} }

View file

@ -91,23 +91,17 @@ final class DrydockLease extends DrydockDAO
$this->setStatus(DrydockLeaseStatus::STATUS_PENDING); $this->setStatus(DrydockLeaseStatus::STATUS_PENDING);
$this->save(); $this->save();
// NOTE: Prevent a race where some eager worker quickly grabs the task $task = PhabricatorWorker::scheduleTask(
// before we can save the Task ID. 'DrydockAllocatorWorker',
$this->getID());
$this->openTransaction(); // NOTE: Scheduling the task might execute it in-process, if we're running
$this->beginReadLocking(); // from a CLI script. Reload the lease to make sure we have the most
// up-to-date information. Normally, this has no effect.
$this->reload();
$this->reload(); $this->setTaskID($task->getID());
$this->save();
$task = PhabricatorWorker::scheduleTask(
'DrydockAllocatorWorker',
$this->getID());
$this->setTaskID($task->getID());
$this->save();
$this->endReadLocking();
$this->saveTransaction();
return $this; return $this;
} }
@ -163,6 +157,8 @@ final class DrydockLease extends DrydockDAO
case DrydockLeaseStatus::STATUS_PENDING: case DrydockLeaseStatus::STATUS_PENDING:
case DrydockLeaseStatus::STATUS_ACQUIRING: case DrydockLeaseStatus::STATUS_ACQUIRING:
break; break;
default:
throw new Exception("Unknown status??");
} }
} }

View file

@ -16,7 +16,7 @@ final class DrydockLog extends DrydockDAO
) + parent::getConfiguration(); ) + parent::getConfiguration();
} }
public function attachResource(DrydockResource $resource) { public function attachResource(DrydockResource $resource = null) {
$this->resource = $resource; $this->resource = $resource;
return $this; return $this;
} }
@ -36,10 +36,16 @@ final class DrydockLog extends DrydockDAO
} }
public function getPolicy($capability) { public function getPolicy($capability) {
if (!$this->getResource()) {
return PhabricatorPolicies::getMostOpenPolicy();
}
return $this->getResource()->getPolicy($capability); return $this->getResource()->getPolicy($capability);
} }
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
if (!$this->getResource()) {
return false;
}
return $this->getResource()->hasAutomaticCapability($capability, $viewer); return $this->getResource()->hasAutomaticCapability($capability, $viewer);
} }

View file

@ -85,14 +85,28 @@ abstract class PhabricatorWorker {
} }
final public static function scheduleTask($task_class, $data) { final public static function scheduleTask($task_class, $data) {
$task = id(new PhabricatorWorkerActiveTask())
->setTaskClass($task_class)
->setData($data);
if (self::$runAllTasksInProcess) { if (self::$runAllTasksInProcess) {
// Do the work in-process.
$worker = newv($task_class, array($data)); $worker = newv($task_class, array($data));
$worker->doWork(); $worker->doWork();
// Now, save a task row and immediately archive it so we can return an
// object with a valid ID.
$task->openTransaction();
$task->save();
$archived = $task->archiveTask(
PhabricatorWorkerArchiveTask::RESULT_SUCCESS,
0);
$task->saveTransaction();
return $archived;
} else { } else {
return id(new PhabricatorWorkerActiveTask()) $task->save();
->setTaskClass($task_class) return $task;
->setData($data)
->save();
} }
} }
@ -105,6 +119,10 @@ abstract class PhabricatorWorker {
* @return void * @return void
*/ */
final public static function waitForTasks(array $task_ids) { final public static function waitForTasks(array $task_ids) {
if (!$task_ids) {
return;
}
$task_table = new PhabricatorWorkerActiveTask(); $task_table = new PhabricatorWorkerActiveTask();
$waiting = array_fuse($task_ids); $waiting = array_fuse($task_ids);
@ -149,7 +167,8 @@ abstract class PhabricatorWorker {
foreach ($tasks as $task) { foreach ($tasks as $task) {
if ($task->getResult() != PhabricatorWorkerArchiveTask::RESULT_SUCCESS) { if ($task->getResult() != PhabricatorWorkerArchiveTask::RESULT_SUCCESS) {
throw new Exception("Task ".$task->getID()." failed!"); throw new Exception(
pht("Task %d failed!", $task->getID()));
} }
} }
} }