Page MenuHomePhabricator

D14236.id.diff
No OneTemporary

D14236.id.diff

diff --git a/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php
@@ -19,6 +19,10 @@
return array();
}
+ public function getViewer() {
+ return PhabricatorUser::getOmnipotentUser();
+ }
+
/* -( Lease Acquisition )-------------------------------------------------- */
@@ -310,4 +314,67 @@
}
}
+
+ /**
+ * Apply standard limits on resource allocation rate.
+ *
+ * @param DrydockBlueprint The blueprint requesting an allocation.
+ * @return bool True if further allocations should be limited.
+ */
+ protected function shouldLimitAllocatingPoolSize(
+ DrydockBlueprint $blueprint) {
+
+ // TODO: If this mechanism sticks around, these values should be
+ // configurable by the blueprint implementation.
+
+ // Limit on total number of active resources.
+ $total_limit = 1;
+
+ // Always allow at least this many allocations to be in flight at once.
+ $min_allowed = 1;
+
+ // Allow this fraction of allocating resources as a fraction of active
+ // resources.
+ $growth_factor = 0.25;
+
+ $resource = new DrydockResource();
+ $conn_r = $resource->establishConnection('r');
+
+ $counts = queryfx_all(
+ $conn_r,
+ 'SELECT status, COUNT(*) N FROM %T WHERE blueprintPHID = %s',
+ $resource->getTableName(),
+ $blueprint->getPHID());
+ $counts = ipull($counts, 'N', 'status');
+
+ $n_alloc = idx($counts, DrydockResourceStatus::STATUS_PENDING, 0);
+ $n_active = idx($counts, DrydockResourceStatus::STATUS_ACTIVE, 0);
+ $n_broken = idx($counts, DrydockResourceStatus::STATUS_BROKEN, 0);
+ $n_released = idx($counts, DrydockResourceStatus::STATUS_RELEASED, 0);
+
+ // If we're at the limit on total active resources, limit additional
+ // allocations.
+ $n_total = ($n_alloc + $n_active + $n_broken + $n_released);
+ if ($n_total >= $total_limit) {
+ return true;
+ }
+
+ // If the number of in-flight allocations is fewer than the minimum number
+ // of allowed allocations, don't impose a limit.
+ if ($n_alloc < $min_allowed) {
+ return false;
+ }
+
+ $allowed_alloc = (int)ceil($n_active * $growth_factor);
+
+ // If the number of in-flight allocation is fewer than the number of
+ // allowed allocations according to the pool growth factor, don't impose
+ // a limit.
+ if ($n_alloc < $allowed_alloc) {
+ return false;
+ }
+
+ return true;
+ }
+
}
diff --git a/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php
@@ -29,6 +29,17 @@
public function canAllocateResourceForLease(
DrydockBlueprint $blueprint,
DrydockLease $lease) {
+ $viewer = $this->getViewer();
+
+ if ($this->shouldLimitAllocatingPoolSize($blueprint)) {
+ return false;
+ }
+
+ // TODO: If we have a pending resource which is compatible with the
+ // configuration for this lease, prevent a new allocation? Otherwise the
+ // queue can fill up with copies of requests from the same lease. But
+ // maybe we can deal with this with "pre-leasing"?
+
return true;
}
@@ -37,6 +48,12 @@
DrydockResource $resource,
DrydockLease $lease) {
+ // Don't hand out leases on working copies which have not activated, since
+ // it may take an arbitrarily long time for them to acquire a host.
+ if (!$resource->isActive()) {
+ return false;
+ }
+
$need_map = $lease->getAttribute('repositories.map');
if (!is_array($need_map)) {
return false;
@@ -320,8 +337,10 @@
}
private function loadRepositories(array $phids) {
+ $viewer = $this->getViewer();
+
$repositories = id(new PhabricatorRepositoryQuery())
- ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->setViewer($viewer)
->withPHIDs($phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
@@ -353,7 +372,7 @@
}
private function loadHostLease(DrydockResource $resource) {
- $viewer = PhabricatorUser::getOmnipotentUser();
+ $viewer = $this->getViewer();
$lease_phid = $resource->getAttribute('host.leasePHID');
diff --git a/src/applications/drydock/storage/DrydockResource.php b/src/applications/drydock/storage/DrydockResource.php
--- a/src/applications/drydock/storage/DrydockResource.php
+++ b/src/applications/drydock/storage/DrydockResource.php
@@ -293,6 +293,15 @@
}
}
+ public function isActive() {
+ switch ($this->getStatus()) {
+ case DrydockResourceStatus::STATUS_ACTIVE:
+ return true;
+ }
+
+ return false;
+ }
+
public function logEvent($type, array $data = array()) {
$log = id(new DrydockLog())
->setEpoch(PhabricatorTime::getNow())
diff --git a/src/applications/drydock/worker/DrydockLeaseUpdateWorker.php b/src/applications/drydock/worker/DrydockLeaseUpdateWorker.php
--- a/src/applications/drydock/worker/DrydockLeaseUpdateWorker.php
+++ b/src/applications/drydock/worker/DrydockLeaseUpdateWorker.php
@@ -535,7 +535,7 @@
// If this lease has been acquired but not activated, queue a task to
// activate it.
if ($lease->getStatus() == DrydockLeaseStatus::STATUS_ACQUIRED) {
- PhabricatorWorker::scheduleTask(
+ $this->queueTask(
__CLASS__,
array(
'leasePHID' => $lease->getPHID(),
@@ -691,7 +691,14 @@
->setStatus(DrydockLeaseStatus::STATUS_BROKEN)
->save();
- $lease->scheduleUpdate();
+ $this->queueTask(
+ __CLASS__,
+ array(
+ 'leasePHID' => $lease->getPHID(),
+ ),
+ array(
+ 'objectPHID' => $lease->getPHID(),
+ ));
$lease->logEvent(
DrydockLeaseActivationFailureLogType::LOGCONST,

File Metadata

Mime Type
text/plain
Expires
Thu, Oct 24, 2:19 PM (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6738445
Default Alt Text
D14236.id.diff (6 KB)

Event Timeline