3 final class DrydockRepositoryOperationUpdateWorker
4 extends DrydockWorker
{
6 protected function doWork() {
7 $operation_phid = $this->getTaskDataValue('operationPHID');
9 $hash = PhabricatorHash
::digestForIndex($operation_phid);
10 $lock_key = 'drydock.operation:'.$hash;
12 $lock = PhabricatorGlobalLock
::newLock($lock_key)
16 $operation = $this->loadOperation($operation_phid);
17 $this->handleUpdate($operation);
18 } catch (Exception
$ex) {
27 private function handleUpdate(DrydockRepositoryOperation
$operation) {
28 $operation_state = $operation->getOperationState();
30 switch ($operation_state) {
31 case DrydockRepositoryOperation
::STATE_WAIT
:
33 ->setOperationState(DrydockRepositoryOperation
::STATE_WORK
)
36 case DrydockRepositoryOperation
::STATE_WORK
:
38 case DrydockRepositoryOperation
::STATE_DONE
:
39 case DrydockRepositoryOperation
::STATE_FAIL
:
40 // No more processing for these requests.
44 // TODO: We should probably check for other running operations with lower
45 // IDs and the same repository target and yield to them here? That is,
46 // enforce sequential evaluation of operations against the same target so
47 // that if you land "A" and then land "B", we always finish "A" first.
48 // For now, just let stuff happen in any order. We can't lease until
49 // we know we're good to move forward because we might deadlock if we do:
50 // we're waiting for another operation to complete, and that operation is
51 // waiting for a lease we're holding.
54 $lease = $this->loadWorkingCopyLease($operation);
56 $interface = $lease->getInterface(
57 DrydockCommandInterface
::INTERFACE_TYPE
);
59 // No matter what happens here, destroy the lease away once we're done.
60 $lease->setReleaseOnDestruction(true);
62 $operation->attachWorkingCopyLease($lease);
64 $operation->logEvent(DrydockOperationWorkLogType
::LOGCONST
);
66 $operation->applyOperation($interface);
68 } catch (PhabricatorWorkerYieldException
$ex) {
70 } catch (Exception
$ex) {
72 ->setOperationState(DrydockRepositoryOperation
::STATE_FAIL
)
78 ->setOperationState(DrydockRepositoryOperation
::STATE_DONE
)
81 // TODO: Once we have sequencing, we could awaken the next operation
82 // against this target after finishing or failing.
85 private function loadWorkingCopyLease(
86 DrydockRepositoryOperation
$operation) {
87 $viewer = $this->getViewer();
89 // TODO: This is very similar to leasing in Harbormaster, maybe we can
90 // share some of the logic?
92 $working_copy = new DrydockWorkingCopyBlueprintImplementation();
93 $working_copy_type = $working_copy->getType();
95 $lease_phid = $operation->getProperty('exec.leasePHID');
97 $lease = id(new DrydockLeaseQuery())
99 ->withPHIDs(array($lease_phid))
102 throw new PhabricatorWorkerPermanentFailureException(
104 'Lease "%s" could not be loaded.',
108 $repository = $operation->getRepository();
110 $allowed_phids = $repository->getAutomationBlueprintPHIDs();
111 $authorizing_phid = $repository->getPHID();
113 $lease = DrydockLease
::initializeNewLease()
114 ->setResourceType($working_copy_type)
115 ->setOwnerPHID($operation->getPHID())
116 ->setAuthorizingPHID($authorizing_phid)
117 ->setAllowedBlueprintPHIDs($allowed_phids);
119 $map = $this->buildRepositoryMap($operation);
121 $lease->setAttribute('repositories.map', $map);
123 $task_id = $this->getCurrentWorkerTaskID();
125 $lease->setAwakenTaskIDs(array($task_id));
129 ->setWorkingCopyLeasePHID($lease->getPHID())
132 $lease->queueForActivation();
135 if ($lease->isActivating()) {
136 throw new PhabricatorWorkerYieldException(15);
139 if (!$lease->isActive()) {
140 $vcs_error = $working_copy->getCommandError($lease);
143 ->setCommandError($vcs_error)
147 throw new PhabricatorWorkerPermanentFailureException(
149 'Lease "%s" never activated.',
156 private function buildRepositoryMap(DrydockRepositoryOperation
$operation) {
157 $repository = $operation->getRepository();
159 $target = $operation->getRepositoryTarget();
160 list($type, $name) = explode(':', $target, 2);
173 'Unknown repository operation target type "%s" (in target "%s").',
178 $spec['merges'] = $operation->getWorkingCopyMerges();
181 $map[$repository->getCloneName()] = array(
182 'phid' => $repository->getPHID(),