1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 23:02:42 +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 $ids;
private $phids; private $phids;
private $blueprintClasses;
private $datasourceQuery; private $datasourceQuery;
public function withIDs(array $ids) { public function withIDs(array $ids) {
@ -16,63 +17,89 @@ final class DrydockBlueprintQuery extends DrydockQuery {
return $this; return $this;
} }
public function withBlueprintClasses(array $classes) {
$this->blueprintClasses = $classes;
return $this;
}
public function withDatasourceQuery($query) { public function withDatasourceQuery($query) {
$this->datasourceQuery = $query; $this->datasourceQuery = $query;
return $this; return $this;
} }
public function newResultObject() {
return new DrydockBlueprint();
}
protected function loadPage() { protected function loadPage() {
$table = new DrydockBlueprint(); return $this->loadStandardPage($this->newResultObject());
$conn_r = $table->establishConnection('r'); }
$data = queryfx_all( protected function willFilterPage(array $blueprints) {
$conn_r, $impls = DrydockBlueprintImplementation::getAllBlueprintImplementations();
'SELECT blueprint.* FROM %T blueprint %Q %Q %Q', foreach ($blueprints as $key => $blueprint) {
$table->getTableName(), $impl = idx($impls, $blueprint->getClassName());
$this->buildWhereClause($conn_r), if (!$impl) {
$this->buildOrderClause($conn_r), $this->didRejectResult($blueprint);
$this->buildLimitClause($conn_r)); unset($blueprints[$key]);
continue;
$blueprints = $table->loadAllFromArray($data);
$implementations =
DrydockBlueprintImplementation::getAllBlueprintImplementations();
foreach ($blueprints as $blueprint) {
if (array_key_exists($blueprint->getClassName(), $implementations)) {
$blueprint->attachImplementation(
$implementations[$blueprint->getClassName()]);
} }
$impl = clone $impl;
$blueprint->attachImplementation($impl);
} }
return $blueprints; return $blueprints;
} }
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = array(); $where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) { if ($this->ids !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'id IN (%Ld)', 'id IN (%Ld)',
$this->ids); $this->ids);
} }
if ($this->phids !== null) { if ($this->phids !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'phid IN (%Ls)', 'phid IN (%Ls)',
$this->phids); $this->phids);
} }
if ($this->datasourceQuery !== null) { if ($this->datasourceQuery !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'blueprintName LIKE %>', 'blueprintName LIKE %>',
$this->datasourceQuery); $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; return $this;
} }
public function newResultObject() {
return new DrydockLease();
}
public function withDatasourceQuery($query) { public function withDatasourceQuery($query) {
$this->datasourceQuery = $query; $this->datasourceQuery = $query;
return $this; return $this;
} }
public function newResultObject() {
return new DrydockLease();
}
protected function loadPage() { protected function loadPage() {
return $this->loadStandardPage($this->newResultObject()); return $this->loadStandardPage($this->newResultObject());
} }

View file

@ -39,71 +39,82 @@ final class DrydockResourceQuery extends DrydockQuery {
return $this; return $this;
} }
public function newResultObject() {
return new DrydockResource();
}
protected function loadPage() { protected function loadPage() {
$table = new DrydockResource(); return $this->loadStandardPage($this->newResultObject());
$conn_r = $table->establishConnection('r'); }
$data = queryfx_all( protected function willFilterPage(array $resources) {
$conn_r, $blueprint_phids = mpull($resources, 'getBlueprintPHID');
'SELECT resource.* FROM %T resource %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$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; return $resources;
} }
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = array(); $where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) { if ($this->ids !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'id IN (%Ld)', 'id IN (%Ld)',
$this->ids); $this->ids);
} }
if ($this->phids !== null) { if ($this->phids !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'phid IN (%Ls)', 'phid IN (%Ls)',
$this->phids); $this->phids);
} }
if ($this->types !== null) { if ($this->types !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'type IN (%Ls)', 'type IN (%Ls)',
$this->types); $this->types);
} }
if ($this->statuses !== null) { if ($this->statuses !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'status IN (%Ls)', 'status IN (%Ls)',
$this->statuses); $this->statuses);
} }
if ($this->blueprintPHIDs !== null) { if ($this->blueprintPHIDs !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'blueprintPHID IN (%Ls)', 'blueprintPHID IN (%Ls)',
$this->blueprintPHIDs); $this->blueprintPHIDs);
} }
if ($this->datasourceQuery !== null) { if ($this->datasourceQuery !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'name LIKE %>', 'name LIKE %>',
$this->datasourceQuery); $this->datasourceQuery);
} }
$where[] = $this->buildPagingClause($conn_r); return $where;
return $this->formatWhereClause($where);
} }
} }

View file

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