Path: blob/master/src/applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php
12256 views
<?php12final class DrydockRepositoryOperationUpdateWorker3extends DrydockWorker {45protected function doWork() {6$operation_phid = $this->getTaskDataValue('operationPHID');78$hash = PhabricatorHash::digestForIndex($operation_phid);9$lock_key = 'drydock.operation:'.$hash;1011$lock = PhabricatorGlobalLock::newLock($lock_key)12->lock(1);1314try {15$operation = $this->loadOperation($operation_phid);16$this->handleUpdate($operation);17} catch (Exception $ex) {18$lock->unlock();19throw $ex;20}2122$lock->unlock();23}242526private function handleUpdate(DrydockRepositoryOperation $operation) {27$operation_state = $operation->getOperationState();2829switch ($operation_state) {30case DrydockRepositoryOperation::STATE_WAIT:31$operation32->setOperationState(DrydockRepositoryOperation::STATE_WORK)33->save();34break;35case DrydockRepositoryOperation::STATE_WORK:36break;37case DrydockRepositoryOperation::STATE_DONE:38case DrydockRepositoryOperation::STATE_FAIL:39// No more processing for these requests.40return;41}4243// TODO: We should probably check for other running operations with lower44// IDs and the same repository target and yield to them here? That is,45// enforce sequential evaluation of operations against the same target so46// that if you land "A" and then land "B", we always finish "A" first.47// For now, just let stuff happen in any order. We can't lease until48// we know we're good to move forward because we might deadlock if we do:49// we're waiting for another operation to complete, and that operation is50// waiting for a lease we're holding.5152try {53$lease = $this->loadWorkingCopyLease($operation);5455$interface = $lease->getInterface(56DrydockCommandInterface::INTERFACE_TYPE);5758// No matter what happens here, destroy the lease away once we're done.59$lease->setReleaseOnDestruction(true);6061$operation->attachWorkingCopyLease($lease);6263$operation->logEvent(DrydockOperationWorkLogType::LOGCONST);6465$operation->applyOperation($interface);6667} catch (PhabricatorWorkerYieldException $ex) {68throw $ex;69} catch (Exception $ex) {70$operation71->setOperationState(DrydockRepositoryOperation::STATE_FAIL)72->save();73throw $ex;74}7576$operation77->setOperationState(DrydockRepositoryOperation::STATE_DONE)78->save();7980// TODO: Once we have sequencing, we could awaken the next operation81// against this target after finishing or failing.82}8384private function loadWorkingCopyLease(85DrydockRepositoryOperation $operation) {86$viewer = $this->getViewer();8788// TODO: This is very similar to leasing in Harbormaster, maybe we can89// share some of the logic?9091$working_copy = new DrydockWorkingCopyBlueprintImplementation();92$working_copy_type = $working_copy->getType();9394$lease_phid = $operation->getProperty('exec.leasePHID');95if ($lease_phid) {96$lease = id(new DrydockLeaseQuery())97->setViewer($viewer)98->withPHIDs(array($lease_phid))99->executeOne();100if (!$lease) {101throw new PhabricatorWorkerPermanentFailureException(102pht(103'Lease "%s" could not be loaded.',104$lease_phid));105}106} else {107$repository = $operation->getRepository();108109$allowed_phids = $repository->getAutomationBlueprintPHIDs();110$authorizing_phid = $repository->getPHID();111112$lease = DrydockLease::initializeNewLease()113->setResourceType($working_copy_type)114->setOwnerPHID($operation->getPHID())115->setAuthorizingPHID($authorizing_phid)116->setAllowedBlueprintPHIDs($allowed_phids);117118$map = $this->buildRepositoryMap($operation);119120$lease->setAttribute('repositories.map', $map);121122$task_id = $this->getCurrentWorkerTaskID();123if ($task_id) {124$lease->setAwakenTaskIDs(array($task_id));125}126127$operation128->setWorkingCopyLeasePHID($lease->getPHID())129->save();130131$lease->queueForActivation();132}133134if ($lease->isActivating()) {135throw new PhabricatorWorkerYieldException(15);136}137138if (!$lease->isActive()) {139$vcs_error = $working_copy->getCommandError($lease);140if ($vcs_error) {141$operation142->setCommandError($vcs_error)143->save();144}145146throw new PhabricatorWorkerPermanentFailureException(147pht(148'Lease "%s" never activated.',149$lease->getPHID()));150}151152return $lease;153}154155private function buildRepositoryMap(DrydockRepositoryOperation $operation) {156$repository = $operation->getRepository();157158$target = $operation->getRepositoryTarget();159list($type, $name) = explode(':', $target, 2);160switch ($type) {161case 'branch':162$spec = array(163'branch' => $name,164);165break;166case 'none':167$spec = array();168break;169default:170throw new Exception(171pht(172'Unknown repository operation target type "%s" (in target "%s").',173$type,174$target));175}176177$spec['merges'] = $operation->getWorkingCopyMerges();178179$map = array();180$map[$repository->getCloneName()] = array(181'phid' => $repository->getPHID(),182'default' => true,183) + $spec;184185return $map;186}187}188189190