private function handleUpdate(DrydockRepositoryOperation $operation) { $viewer = $this->getViewer(); $operation_state = $operation->getOperationState(); switch ($operation_state) { case DrydockRepositoryOperation::STATE_WAIT: $operation->setOperationState(DrydockRepositoryOperation::STATE_WORK)->save(); break; case DrydockRepositoryOperation::STATE_WORK: break; case DrydockRepositoryOperation::STATE_DONE: case DrydockRepositoryOperation::STATE_FAIL: // No more processing for these requests. return; } // TODO: We should probably check for other running operations with lower // IDs and the same repository target and yield to them here? That is, // enforce sequential evaluation of operations against the same target so // that if you land "A" and then land "B", we always finish "A" first. // For now, just let stuff happen in any order. We can't lease until // we know we're good to move forward because we might deadlock if we do: // we're waiting for another operation to complete, and that operation is // waiting for a lease we're holding. try { $operation->getImplementation()->setViewer($viewer); $lease = $this->loadWorkingCopyLease($operation); $interface = $lease->getInterface(DrydockCommandInterface::INTERFACE_TYPE); // No matter what happens here, destroy the lease away once we're done. $lease->releaseOnDestruction(true); $operation->applyOperation($interface); } catch (PhabricatorWorkerYieldException $ex) { throw $ex; } catch (Exception $ex) { $operation->setOperationState(DrydockRepositoryOperation::STATE_FAIL)->save(); throw $ex; } $operation->setOperationState(DrydockRepositoryOperation::STATE_DONE)->save(); // TODO: Once we have sequencing, we could awaken the next operation // against this target after finishing or failing. }