diff --git a/src/applications/drydock/query/DrydockLeaseQuery.php b/src/applications/drydock/query/DrydockLeaseQuery.php --- a/src/applications/drydock/query/DrydockLeaseQuery.php +++ b/src/applications/drydock/query/DrydockLeaseQuery.php @@ -9,6 +9,8 @@ private $statuses; private $datasourceQuery; private $needUnconsumedCommands; + private $minModified; + private $maxModified; public function withIDs(array $ids) { $this->ids = $ids; @@ -40,6 +42,12 @@ return $this; } + public function withDateModifiedBetween($min_epoch, $max_epoch) { + $this->minModified = $min_epoch; + $this->maxModified = $max_epoch; + return $this; + } + public function needUnconsumedCommands($need) { $this->needUnconsumedCommands = $need; return $this; @@ -146,6 +154,20 @@ (int)$this->datasourceQuery); } + if ($this->minModified !== null) { + $where[] = qsprintf( + $conn, + 'dateModified >= %d', + $this->minModified); + } + + if ($this->maxModified !== null) { + $where[] = qsprintf( + $conn, + 'dateModified <= %d', + $this->maxModified); + } + return $where; } diff --git a/src/applications/drydock/storage/DrydockLease.php b/src/applications/drydock/storage/DrydockLease.php --- a/src/applications/drydock/storage/DrydockLease.php +++ b/src/applications/drydock/storage/DrydockLease.php @@ -111,6 +111,9 @@ 'key_owner' => array( 'columns' => array('ownerPHID'), ), + 'key_recent' => array( + 'columns' => array('resourcePHID', 'dateModified'), + ), ), ) + parent::getConfiguration(); } diff --git a/src/applications/drydock/worker/DrydockWorker.php b/src/applications/drydock/worker/DrydockWorker.php --- a/src/applications/drydock/worker/DrydockWorker.php +++ b/src/applications/drydock/worker/DrydockWorker.php @@ -203,14 +203,15 @@ // from one another forever without making progress, so make resources // immune to reclamation for a little while after they activate or update. + $now = PhabricatorTime::getNow(); + $max_epoch = ($now - phutil_units('3 minutes in seconds')); + // TODO: It would be nice to use a more narrow time here, like "last // activation or lease release", but we don't currently store that // anywhere. $updated = $resource->getDateModified(); - $now = PhabricatorTime::getNow(); - $ago = ($now - $updated); - if ($ago < phutil_units('3 minutes in seconds')) { + if ($updated > $max_epoch) { return false; } @@ -233,6 +234,21 @@ return false; } + // See T13676. Don't reclaim a resource if a lease recently released. + $leases = id(new DrydockLeaseQuery()) + ->setViewer($viewer) + ->withResourcePHIDs(array($resource->getPHID())) + ->withStatuses( + array( + DrydockLeaseStatus::STATUS_DESTROYED, + )) + ->withDateModifiedBetween($max_epoch, null) + ->setLimit(1) + ->execute(); + if ($leases) { + return false; + } + return true; }