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

Modernize Drydock Query + Attach code

Summary:
Ref T9253. Some of the Drydock code is pretty old. This applies standard modernizations to it:

  - Modernize Query classes to use stuff like `buildWhereClauseParts()` and `loadStandardPage()`.
  - Modernize all the getX() / attachX() stuff. In particular:
    - Require and attach implementations to Blueprints.
    - Require and attach Blueprints to Resources.
    - BlueprintImplementations are now always unique per-Blueprint so they can store/cache state if they want without running over one another.
    - BlueprintImplementations are now passed a `$blueprint`, like other similar APIs (this could go various ways but I generally like this as a balance of concerns).

NOTE: This probably doesn't run on its own, I'm just trying to split the next diff (core allocator stuff) up a bit and these pieces are all pretty standard.

Test Plan:
  - Not much; see next revision or two.
  - Clicked around Resource and Blueprint lists.

Reviewers: chad, hach-que

Reviewed By: chad, hach-que

Maniphest Tasks: T9253

Differential Revision: https://secure.phabricator.com/D14113
This commit is contained in:
epriestley 2015-09-21 04:42:04 -07:00
parent 635e9c6075
commit 5362d3366c
4 changed files with 104 additions and 58 deletions

View file

@ -4,6 +4,7 @@ final class DrydockBlueprintQuery extends DrydockQuery {
private $ids;
private $phids;
private $blueprintClasses;
private $datasourceQuery;
public function withIDs(array $ids) {
@ -16,63 +17,89 @@ final class DrydockBlueprintQuery extends DrydockQuery {
return $this;
}
public function withBlueprintClasses(array $classes) {
$this->blueprintClasses = $classes;
return $this;
}
public function withDatasourceQuery($query) {
$this->datasourceQuery = $query;
return $this;
}
public function newResultObject() {
return new DrydockBlueprint();
}
protected function loadPage() {
$table = new DrydockBlueprint();
$conn_r = $table->establishConnection('r');
return $this->loadStandardPage($this->newResultObject());
}
$data = queryfx_all(
$conn_r,
'SELECT blueprint.* FROM %T blueprint %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$blueprints = $table->loadAllFromArray($data);
$implementations =
DrydockBlueprintImplementation::getAllBlueprintImplementations();
foreach ($blueprints as $blueprint) {
if (array_key_exists($blueprint->getClassName(), $implementations)) {
$blueprint->attachImplementation(
$implementations[$blueprint->getClassName()]);
protected function willFilterPage(array $blueprints) {
$impls = DrydockBlueprintImplementation::getAllBlueprintImplementations();
foreach ($blueprints as $key => $blueprint) {
$impl = idx($impls, $blueprint->getClassName());
if (!$impl) {
$this->didRejectResult($blueprint);
unset($blueprints[$key]);
continue;
}
$impl = clone $impl;
$blueprint->attachImplementation($impl);
}
return $blueprints;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->datasourceQuery !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'blueprintName LIKE %>',
$this->datasourceQuery);
}
return $this->formatWhereClause($where);
if ($this->blueprintClasses !== null) {
$where[] = qsprintf(
$conn,
'className IN (%Ls)',
$this->blueprintClasses);
}
return $where;
}
public function getOrderableColumns() {
// TODO: Blueprints implement CustomFields, but can not be ordered by
// custom field classes because the custom fields are not global. There
// is no graceful way to handle this in ApplicationSearch at the moment.
// Just brute force around it until we can clean this up.
return array(
'id' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'id',
'reverse' => false,
'type' => 'int',
'unique' => true,
),
);
}
}

View file

@ -28,15 +28,15 @@ final class DrydockLeaseQuery extends DrydockQuery {
return $this;
}
public function newResultObject() {
return new DrydockLease();
}
public function withDatasourceQuery($query) {
$this->datasourceQuery = $query;
return $this;
}
public function newResultObject() {
return new DrydockLease();
}
protected function loadPage() {
return $this->loadStandardPage($this->newResultObject());
}

View file

@ -39,71 +39,82 @@ final class DrydockResourceQuery extends DrydockQuery {
return $this;
}
public function newResultObject() {
return new DrydockResource();
}
protected function loadPage() {
$table = new DrydockResource();
$conn_r = $table->establishConnection('r');
return $this->loadStandardPage($this->newResultObject());
}
$data = queryfx_all(
$conn_r,
'SELECT resource.* FROM %T resource %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
protected function willFilterPage(array $resources) {
$blueprint_phids = mpull($resources, 'getBlueprintPHID');
$resources = $table->loadAllFromArray($data);
$blueprints = id(new DrydockBlueprintQuery())
->setViewer($this->getViewer())
->withPHIDs($blueprint_phids)
->execute();
$blueprints = mpull($blueprints, null, 'getPHID');
foreach ($resources as $key => $resource) {
$blueprint = idx($blueprints, $resource->getBlueprintPHID());
if (!$blueprint) {
$this->didRejectResult($resource);
unset($resources[$key]);
continue;
}
$resource->attachBlueprint($blueprint);
}
return $resources;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->types !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'type IN (%Ls)',
$this->types);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'status IN (%Ls)',
$this->statuses);
}
if ($this->blueprintPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'blueprintPHID IN (%Ls)',
$this->blueprintPHIDs);
}
if ($this->datasourceQuery !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'name LIKE %>',
$this->datasourceQuery);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
return $where;
}
}

View file

@ -14,7 +14,7 @@ final class DrydockResource extends DrydockDAO
protected $capabilities = array();
protected $ownerPHID;
private $blueprint;
private $blueprint = self::ATTACHABLE;
protected function getConfiguration() {
return array(
@ -65,16 +65,24 @@ final class DrydockResource extends DrydockDAO
}
public function getBlueprint() {
// TODO: Policy stuff.
if (empty($this->blueprint)) {
$blueprint = id(new DrydockBlueprint())
->loadOneWhere('phid = %s', $this->blueprintPHID);
$this->blueprint = $blueprint->getImplementation();
}
return $this->blueprint;
return $this->assertAttached($this->blueprint);
}
public function attachBlueprint(DrydockBlueprint $blueprint) {
$this->blueprint = $blueprint;
return $this;
}
public function canAllocateLease(DrydockLease $lease) {
return $this->getBlueprint()->canAllocateLeaseOnResource(
$this,
$lease);
}
public function closeResource() {
// TODO: This is super broken and will race other lease writers!
$this->openTransaction();
$statuses = array(
DrydockLeaseStatus::STATUS_PENDING,