@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+104 -58
+52 -25
src/applications/drydock/query/DrydockBlueprintQuery.php
··· 4 4 5 5 private $ids; 6 6 private $phids; 7 + private $blueprintClasses; 7 8 private $datasourceQuery; 8 9 9 10 public function withIDs(array $ids) { ··· 16 17 return $this; 17 18 } 18 19 20 + public function withBlueprintClasses(array $classes) { 21 + $this->blueprintClasses = $classes; 22 + return $this; 23 + } 24 + 19 25 public function withDatasourceQuery($query) { 20 26 $this->datasourceQuery = $query; 21 27 return $this; 28 + } 29 + 30 + public function newResultObject() { 31 + return new DrydockBlueprint(); 22 32 } 23 33 24 34 protected function loadPage() { 25 - $table = new DrydockBlueprint(); 26 - $conn_r = $table->establishConnection('r'); 35 + return $this->loadStandardPage($this->newResultObject()); 36 + } 27 37 28 - $data = queryfx_all( 29 - $conn_r, 30 - 'SELECT blueprint.* FROM %T blueprint %Q %Q %Q', 31 - $table->getTableName(), 32 - $this->buildWhereClause($conn_r), 33 - $this->buildOrderClause($conn_r), 34 - $this->buildLimitClause($conn_r)); 35 - 36 - $blueprints = $table->loadAllFromArray($data); 37 - 38 - $implementations = 39 - DrydockBlueprintImplementation::getAllBlueprintImplementations(); 40 - 41 - foreach ($blueprints as $blueprint) { 42 - if (array_key_exists($blueprint->getClassName(), $implementations)) { 43 - $blueprint->attachImplementation( 44 - $implementations[$blueprint->getClassName()]); 38 + protected function willFilterPage(array $blueprints) { 39 + $impls = DrydockBlueprintImplementation::getAllBlueprintImplementations(); 40 + foreach ($blueprints as $key => $blueprint) { 41 + $impl = idx($impls, $blueprint->getClassName()); 42 + if (!$impl) { 43 + $this->didRejectResult($blueprint); 44 + unset($blueprints[$key]); 45 + continue; 45 46 } 47 + $impl = clone $impl; 48 + $blueprint->attachImplementation($impl); 46 49 } 47 50 48 51 return $blueprints; 49 52 } 50 53 51 - protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { 52 - $where = array(); 54 + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 55 + $where = parent::buildWhereClauseParts($conn); 53 56 54 57 if ($this->ids !== null) { 55 58 $where[] = qsprintf( 56 - $conn_r, 59 + $conn, 57 60 'id IN (%Ld)', 58 61 $this->ids); 59 62 } 60 63 61 64 if ($this->phids !== null) { 62 65 $where[] = qsprintf( 63 - $conn_r, 66 + $conn, 64 67 'phid IN (%Ls)', 65 68 $this->phids); 66 69 } 67 70 68 71 if ($this->datasourceQuery !== null) { 69 72 $where[] = qsprintf( 70 - $conn_r, 73 + $conn, 71 74 'blueprintName LIKE %>', 72 75 $this->datasourceQuery); 73 76 } 74 77 75 - return $this->formatWhereClause($where); 78 + if ($this->blueprintClasses !== null) { 79 + $where[] = qsprintf( 80 + $conn, 81 + 'className IN (%Ls)', 82 + $this->blueprintClasses); 83 + } 84 + 85 + return $where; 86 + } 87 + 88 + public function getOrderableColumns() { 89 + // TODO: Blueprints implement CustomFields, but can not be ordered by 90 + // custom field classes because the custom fields are not global. There 91 + // is no graceful way to handle this in ApplicationSearch at the moment. 92 + // Just brute force around it until we can clean this up. 93 + 94 + return array( 95 + 'id' => array( 96 + 'table' => $this->getPrimaryTableAlias(), 97 + 'column' => 'id', 98 + 'reverse' => false, 99 + 'type' => 'int', 100 + 'unique' => true, 101 + ), 102 + ); 76 103 } 77 104 78 105 }
+4 -4
src/applications/drydock/query/DrydockLeaseQuery.php
··· 28 28 return $this; 29 29 } 30 30 31 - public function newResultObject() { 32 - return new DrydockLease(); 33 - } 34 - 35 31 public function withDatasourceQuery($query) { 36 32 $this->datasourceQuery = $query; 37 33 return $this; 34 + } 35 + 36 + public function newResultObject() { 37 + return new DrydockLease(); 38 38 } 39 39 40 40 protected function loadPage() {
+32 -21
src/applications/drydock/query/DrydockResourceQuery.php
··· 39 39 return $this; 40 40 } 41 41 42 + public function newResultObject() { 43 + return new DrydockResource(); 44 + } 45 + 42 46 protected function loadPage() { 43 - $table = new DrydockResource(); 44 - $conn_r = $table->establishConnection('r'); 47 + return $this->loadStandardPage($this->newResultObject()); 48 + } 45 49 46 - $data = queryfx_all( 47 - $conn_r, 48 - 'SELECT resource.* FROM %T resource %Q %Q %Q', 49 - $table->getTableName(), 50 - $this->buildWhereClause($conn_r), 51 - $this->buildOrderClause($conn_r), 52 - $this->buildLimitClause($conn_r)); 50 + protected function willFilterPage(array $resources) { 51 + $blueprint_phids = mpull($resources, 'getBlueprintPHID'); 52 + 53 + $blueprints = id(new DrydockBlueprintQuery()) 54 + ->setViewer($this->getViewer()) 55 + ->withPHIDs($blueprint_phids) 56 + ->execute(); 57 + $blueprints = mpull($blueprints, null, 'getPHID'); 53 58 54 - $resources = $table->loadAllFromArray($data); 59 + foreach ($resources as $key => $resource) { 60 + $blueprint = idx($blueprints, $resource->getBlueprintPHID()); 61 + if (!$blueprint) { 62 + $this->didRejectResult($resource); 63 + unset($resources[$key]); 64 + continue; 65 + } 66 + $resource->attachBlueprint($blueprint); 67 + } 55 68 56 69 return $resources; 57 70 } 58 71 59 - protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { 60 - $where = array(); 72 + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 73 + $where = parent::buildWhereClauseParts($conn); 61 74 62 75 if ($this->ids !== null) { 63 76 $where[] = qsprintf( 64 - $conn_r, 77 + $conn, 65 78 'id IN (%Ld)', 66 79 $this->ids); 67 80 } 68 81 69 82 if ($this->phids !== null) { 70 83 $where[] = qsprintf( 71 - $conn_r, 84 + $conn, 72 85 'phid IN (%Ls)', 73 86 $this->phids); 74 87 } 75 88 76 89 if ($this->types !== null) { 77 90 $where[] = qsprintf( 78 - $conn_r, 91 + $conn, 79 92 'type IN (%Ls)', 80 93 $this->types); 81 94 } 82 95 83 96 if ($this->statuses !== null) { 84 97 $where[] = qsprintf( 85 - $conn_r, 98 + $conn, 86 99 'status IN (%Ls)', 87 100 $this->statuses); 88 101 } 89 102 90 103 if ($this->blueprintPHIDs !== null) { 91 104 $where[] = qsprintf( 92 - $conn_r, 105 + $conn, 93 106 'blueprintPHID IN (%Ls)', 94 107 $this->blueprintPHIDs); 95 108 } 96 109 97 110 if ($this->datasourceQuery !== null) { 98 111 $where[] = qsprintf( 99 - $conn_r, 112 + $conn, 100 113 'name LIKE %>', 101 114 $this->datasourceQuery); 102 115 } 103 116 104 - $where[] = $this->buildPagingClause($conn_r); 105 - 106 - return $this->formatWhereClause($where); 117 + return $where; 107 118 } 108 119 109 120 }
+16 -8
src/applications/drydock/storage/DrydockResource.php
··· 14 14 protected $capabilities = array(); 15 15 protected $ownerPHID; 16 16 17 - private $blueprint; 17 + private $blueprint = self::ATTACHABLE; 18 18 19 19 protected function getConfiguration() { 20 20 return array( ··· 65 65 } 66 66 67 67 public function getBlueprint() { 68 - // TODO: Policy stuff. 69 - if (empty($this->blueprint)) { 70 - $blueprint = id(new DrydockBlueprint()) 71 - ->loadOneWhere('phid = %s', $this->blueprintPHID); 72 - $this->blueprint = $blueprint->getImplementation(); 73 - } 74 - return $this->blueprint; 68 + return $this->assertAttached($this->blueprint); 69 + } 70 + 71 + public function attachBlueprint(DrydockBlueprint $blueprint) { 72 + $this->blueprint = $blueprint; 73 + return $this; 74 + } 75 + 76 + public function canAllocateLease(DrydockLease $lease) { 77 + return $this->getBlueprint()->canAllocateLeaseOnResource( 78 + $this, 79 + $lease); 75 80 } 76 81 77 82 public function closeResource() { 83 + 84 + // TODO: This is super broken and will race other lease writers! 85 + 78 86 $this->openTransaction(); 79 87 $statuses = array( 80 88 DrydockLeaseStatus::STATUS_PENDING,