@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.

Allow Drydock leases to expire after a time limit

Summary: Ref T6569. If a lease is activated with an expiration date, schedule a task to try to clean it up after that time.

Test Plan:
- Used `bin/drydock lease ... --until ...` to activate a lease in the near future.
- Waited for a bit.
- Saw it expire and get destroyed at the scheduled time.

Reviewers: hach-que, chad

Reviewed By: chad

Maniphest Tasks: T6569

Differential Revision: https://secure.phabricator.com/D14148

+82 -3
+9
src/applications/drydock/controller/DrydockLeaseViewController.php
··· 97 97 private function buildPropertyListView( 98 98 DrydockLease $lease, 99 99 PhabricatorActionListView $actions) { 100 + $viewer = $this->getViewer(); 100 101 101 102 $view = new PHUIPropertyListView(); 102 103 $view->setActionList($actions); ··· 144 145 pht('Resource'), 145 146 pht('No Resource')); 146 147 } 148 + 149 + $until = $lease->getUntil(); 150 + if ($until) { 151 + $until_display = phabricator_datetime($until, $viewer); 152 + } else { 153 + $until_display = phutil_tag('em', array(), pht('Never')); 154 + } 155 + $view->addProperty(pht('Expires'), $until_display); 147 156 148 157 $attributes = $lease->getAttributes(); 149 158 if ($attributes) {
+22
src/applications/drydock/management/DrydockManagementLeaseWorkflow.php
··· 15 15 'help' => pht('Resource type.'), 16 16 ), 17 17 array( 18 + 'name' => 'until', 19 + 'param' => 'time', 20 + 'help' => pht('Set lease expiration time.'), 21 + ), 22 + array( 18 23 'name' => 'attributes', 19 24 'param' => 'name=value,...', 20 25 'help' => pht('Resource specficiation.'), ··· 33 38 '--type')); 34 39 } 35 40 41 + $until = $args->getArg('until'); 42 + if (strlen($until)) { 43 + $until = strtotime($until); 44 + if ($until <= 0) { 45 + throw new PhutilArgumentUsageException( 46 + pht( 47 + 'Unable to parse argument to "%s".', 48 + '--until')); 49 + } 50 + } 51 + 36 52 $attributes = $args->getArg('attributes'); 37 53 if ($attributes) { 38 54 $options = new PhutilSimpleOptions(); ··· 42 58 43 59 $lease = id(new DrydockLease()) 44 60 ->setResourceType($resource_type); 61 + 45 62 if ($attributes) { 46 63 $lease->setAttributes($attributes); 47 64 } 65 + 66 + if ($until) { 67 + $lease->setUntil($until); 68 + } 69 + 48 70 $lease->queueForActivation(); 49 71 50 72 echo tsprintf(
+8 -1
src/applications/drydock/storage/DrydockLease.php
··· 295 295 } 296 296 } 297 297 298 - public function scheduleUpdate() { 298 + public function scheduleUpdate($epoch = null) { 299 299 PhabricatorWorker::scheduleTask( 300 300 'DrydockLeaseUpdateWorker', 301 301 array( 302 302 'leasePHID' => $this->getPHID(), 303 + 'isExpireTask' => ($epoch !== null), 303 304 ), 304 305 array( 305 306 'objectPHID' => $this->getPHID(), 307 + 'delayUntil' => $epoch, 306 308 )); 307 309 } 308 310 ··· 321 323 322 324 if ($need_update) { 323 325 $this->scheduleUpdate(); 326 + } 327 + 328 + $expires = $this->getUntil(); 329 + if ($expires) { 330 + $this->scheduleUpdate($expires); 324 331 } 325 332 } 326 333
+38 -2
src/applications/drydock/worker/DrydockLeaseUpdateWorker.php
··· 11 11 $lock = PhabricatorGlobalLock::newLock($lock_key) 12 12 ->lock(1); 13 13 14 - $lease = $this->loadLease($lease_phid); 15 - $this->updateLease($lease); 14 + try { 15 + $lease = $this->loadLease($lease_phid); 16 + $this->updateLease($lease); 17 + } catch (Exception $ex) { 18 + $lock->unlock(); 19 + throw $ex; 20 + } 16 21 17 22 $lock->unlock(); 18 23 } 19 24 20 25 private function updateLease(DrydockLease $lease) { 26 + if ($lease->getStatus() != DrydockLeaseStatus::STATUS_ACTIVE) { 27 + return; 28 + } 29 + 30 + $viewer = $this->getViewer(); 31 + $drydock_phid = id(new PhabricatorDrydockApplication())->getPHID(); 32 + 33 + // Check if the lease has expired. If it is, we're going to send it a 34 + // release command. This command will be handled immediately below, it 35 + // just generates a command log and improves consistency. 36 + $now = PhabricatorTime::getNow(); 37 + $expires = $lease->getUntil(); 38 + if ($expires && ($expires <= $now)) { 39 + $command = DrydockCommand::initializeNewCommand($viewer) 40 + ->setTargetPHID($lease->getPHID()) 41 + ->setAuthorPHID($drydock_phid) 42 + ->setCommand(DrydockCommand::COMMAND_RELEASE) 43 + ->save(); 44 + } 45 + 21 46 $commands = $this->loadCommands($lease->getPHID()); 22 47 foreach ($commands as $command) { 23 48 if ($lease->getStatus() != DrydockLeaseStatus::STATUS_ACTIVE) { ··· 27 52 } 28 53 29 54 $this->processCommand($lease, $command); 55 + 30 56 $command 31 57 ->setIsConsumed(true) 32 58 ->save(); 59 + } 60 + 61 + // If this is the task which will eventually release the lease after it 62 + // expires but it is still active, reschedule the task to run after the 63 + // lease expires. This can happen if the lease's expiration was pushed 64 + // forward. 65 + if ($lease->getStatus() == DrydockLeaseStatus::STATUS_ACTIVE) { 66 + if ($this->getTaskDataValue('isExpireTask') && $expires) { 67 + throw new PhabricatorWorkerYieldException($expires - $now); 68 + } 33 69 } 34 70 } 35 71
+5
src/infrastructure/daemon/workers/PhabricatorWorker.php
··· 117 117 ->setPriority($priority) 118 118 ->setObjectPHID($object_phid); 119 119 120 + $delay = idx($options, 'delayUntil'); 121 + if ($delay) { 122 + $task->setLeaseExpires($delay); 123 + } 124 + 120 125 if (self::$runAllTasksInProcess) { 121 126 // Do the work in-process. 122 127 $worker = newv($task_class, array($data));