public static function queueDocumentForIndexing($phid, $parameters = null)
 {
     if ($parameters === null) {
         $parameters = array();
     }
     parent::scheduleTask(__CLASS__, array('documentPHID' => $phid, 'parameters' => $parameters), array('priority' => parent::PRIORITY_IMPORT));
 }
 protected function doWork()
 {
     $lock = $this->acquireJobLock();
     $job = $this->loadJob();
     $actor = $this->loadActor($job);
     $status = $job->getStatus();
     switch ($status) {
         case PhabricatorWorkerBulkJob::STATUS_WAITING:
             // This is what we expect. Other statuses indicate some kind of race
             // is afoot.
             break;
         default:
             throw new PhabricatorWorkerPermanentFailureException(pht('Found unexpected job status ("%s").', $status));
     }
     $tasks = $job->createTasks();
     foreach ($tasks as $task) {
         $task->save();
     }
     $this->updateJobStatus($job, PhabricatorWorkerBulkJob::STATUS_RUNNING);
     $lock->unlock();
     foreach ($tasks as $task) {
         PhabricatorWorker::scheduleTask('PhabricatorWorkerBulkJobTaskWorker', array('jobID' => $job->getID(), 'taskID' => $task->getID()), array('priority' => PhabricatorWorker::PRIORITY_BULK));
     }
     $this->updateJob($job);
 }
 private function executeBuildCommand(HarbormasterBuild $build, HarbormasterBuildTransaction $xaction)
 {
     $command = $xaction->getNewValue();
     switch ($command) {
         case HarbormasterBuildCommand::COMMAND_RESTART:
             $issuable = $build->canRestartBuild();
             break;
         case HarbormasterBuildCommand::COMMAND_PAUSE:
             $issuable = $build->canPauseBuild();
             break;
         case HarbormasterBuildCommand::COMMAND_RESUME:
             $issuable = $build->canResumeBuild();
             break;
         case HarbormasterBuildCommand::COMMAND_ABORT:
             $issuable = $build->canAbortBuild();
             break;
         default:
             throw new Exception(pht('Unknown command %s', $command));
     }
     if (!$issuable) {
         return;
     }
     $actor = $this->getActor();
     if (!$build->canIssueCommand($actor, $command)) {
         return;
     }
     id(new HarbormasterBuildCommand())->setAuthorPHID($xaction->getAuthorPHID())->setTargetPHID($build->getPHID())->setCommand($command)->save();
     PhabricatorWorker::scheduleTask('HarbormasterBuildWorker', array('buildID' => $build->getID()), array('objectPHID' => $build->getPHID()));
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $viewer = $request->getUser();
     $build_target_phid = $request->getValue('buildTargetPHID');
     $message_type = $request->getValue('type');
     $build_target = id(new HarbormasterBuildTargetQuery())->setViewer($viewer)->withPHIDs(array($build_target_phid))->executeOne();
     if (!$build_target) {
         throw new Exception(pht('No such build target!'));
     }
     $save = array();
     $lint_messages = $request->getValue('lint', array());
     foreach ($lint_messages as $lint) {
         $save[] = HarbormasterBuildLintMessage::newFromDictionary($build_target, $lint);
     }
     $unit_messages = $request->getValue('unit', array());
     foreach ($unit_messages as $unit) {
         $save[] = HarbormasterBuildUnitMessage::newFromDictionary($build_target, $unit);
     }
     $save[] = HarbormasterBuildMessage::initializeNewMessage($viewer)->setBuildTargetPHID($build_target->getPHID())->setType($message_type);
     $build_target->openTransaction();
     foreach ($save as $object) {
         $object->save();
     }
     $build_target->saveTransaction();
     // If the build has completely paused because all steps are blocked on
     // waiting targets, this will resume it.
     PhabricatorWorker::scheduleTask('HarbormasterBuildWorker', array('buildID' => $build_target->getBuild()->getID()));
     return null;
 }
 public function execute(PhutilArgumentParser $args)
 {
     $console = PhutilConsole::getConsole();
     $viewer = $this->getViewer();
     $subscription_phid = $args->getArg('subscription');
     if (!$subscription_phid) {
         throw new PhutilArgumentUsageException(pht('Specify which subscription to invoice with %s.', '--subscription'));
     }
     $subscription = id(new PhortuneSubscriptionQuery())->setViewer($viewer)->withPHIDs(array($subscription_phid))->needTriggers(true)->executeOne();
     if (!$subscription) {
         throw new PhutilArgumentUsageException(pht('Unable to load subscription with PHID "%s".', $subscription_phid));
     }
     $now = $args->getArg('now');
     $now = $this->parseTimeArgument($now);
     if (!$now) {
         $now = PhabricatorTime::getNow();
     }
     $time_guard = PhabricatorTime::pushTime($now, date_default_timezone_get());
     $console->writeOut("%s\n", pht('Set current time to %s.', phabricator_datetime(PhabricatorTime::getNow(), $viewer)));
     $auto_range = $args->getArg('auto-range');
     $last_arg = $args->getArg('last');
     $next_arg = $args->getARg('next');
     if (!$auto_range && !$last_arg && !$next_arg) {
         throw new PhutilArgumentUsageException(pht('Specify a billing range with %s and %s, or use %s.', '--last', '--next', '--auto-range'));
     } else {
         if (!$auto_range & (!$last_arg || !$next_arg)) {
             throw new PhutilArgumentUsageException(pht('When specifying %s or %s, you must specify both arguments ' . 'to define the beginning and end of the billing range.', '--last', '--next'));
         } else {
             if (!$auto_range && ($last_arg && $next_arg)) {
                 $last_time = $this->parseTimeArgument($args->getArg('last'));
                 $next_time = $this->parseTimeArgument($args->getArg('next'));
             } else {
                 if ($auto_range && ($last_arg || $next_arg)) {
                     throw new PhutilArgumentUsageException(pht('Use either %s or %s and %s to specify the ' . 'billing range, but not both.', '--auto-range', '--last', '--next'));
                 } else {
                     $trigger = $subscription->getTrigger();
                     $event = $trigger->getEvent();
                     if (!$event) {
                         throw new PhutilArgumentUsageException(pht('Unable to calculate %s, this subscription has not been ' . 'scheduled for billing yet. Wait for the trigger daemon to ' . 'schedule the subscription.', '--auto-range'));
                     }
                     $last_time = $event->getLastEventEpoch();
                     $next_time = $event->getNextEventEpoch();
                 }
             }
         }
     }
     $console->writeOut("%s\n", pht('Preparing to invoice subscription "%s" from %s to %s.', $subscription->getSubscriptionName(), $last_time ? phabricator_datetime($last_time, $viewer) : pht('subscription creation'), phabricator_datetime($next_time, $viewer)));
     PhabricatorWorker::setRunAllTasksInProcess(true);
     if (!$args->getArg('force')) {
         $console->writeOut("**<bg:yellow> %s </bg>**\n%s\n", pht('WARNING'), phutil_console_wrap(pht('Manually invoicing will double bill payment accounts if the ' . 'range overlaps an existing or future invoice. This script is ' . 'intended for testing and development, and should not be part ' . 'of routine billing operations. If you continue, you may ' . 'incorrectly overcharge customers.')));
         if (!phutil_console_confirm(pht('Really invoice this subscription?'))) {
             throw new Exception(pht('Declining to invoice.'));
         }
     }
     PhabricatorWorker::scheduleTask('PhortuneSubscriptionWorker', array('subscriptionPHID' => $subscription->getPHID(), 'trigger.last-epoch' => $last_time, 'trigger.this-epoch' => $next_time, 'manual' => true), array('objectPHID' => $subscription->getPHID()));
     return 0;
 }
 public function execute(PhutilArgumentParser $args)
 {
     $console = PhutilConsole::getConsole();
     $console->writeOut("%s\n", pht('Adding many test tasks to worker queue. Use ^C to exit.'));
     $n = 0;
     while (true) {
         PhabricatorWorker::scheduleTask('PhabricatorTestWorker', array());
         if ($n++ % 100 === 0) {
             $console->writeOut('.');
         }
     }
 }
 private function releaseLease(DrydockLease $lease)
 {
     $lease->openTransaction();
     $lease->setStatus(DrydockLeaseStatus::STATUS_RELEASED)->save();
     // TODO: Hold slot locks until destruction?
     DrydockSlotLock::releaseLocks($lease->getPHID());
     $lease->saveTransaction();
     PhabricatorWorker::scheduleTask('DrydockLeaseDestroyWorker', array('leasePHID' => $lease->getPHID()), array('objectPHID' => $lease->getPHID()));
     $resource = $lease->getResource();
     $blueprint = $resource->getBlueprint();
     $blueprint->didReleaseLease($resource, $lease);
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $viewer = $request->getUser();
     $build_target_phid = $request->getValue('buildTargetPHID');
     $message_type = $request->getValue('type');
     $build_target = id(new HarbormasterBuildTargetQuery())->setViewer($viewer)->withPHIDs(array($build_target_phid))->executeOne();
     if (!$build_target) {
         throw new Exception(pht('No such build target!'));
     }
     $message = HarbormasterBuildMessage::initializeNewMessage($viewer)->setBuildTargetPHID($build_target->getPHID())->setType($message_type)->save();
     // If the build has completely paused because all steps are blocked on
     // waiting targets, this will resume it.
     PhabricatorWorker::scheduleTask('HarbormasterBuildWorker', array('buildID' => $build_target->getBuild()->getID()));
     return null;
 }
Пример #9
0
 public function queueForActivation()
 {
     if ($this->getID()) {
         throw new Exception('Only new leases may be queued for activation!');
     }
     $this->setStatus(DrydockLeaseStatus::STATUS_PENDING);
     $this->save();
     $task = PhabricatorWorker::scheduleTask('DrydockAllocatorWorker', $this->getID());
     // NOTE: Scheduling the task might execute it in-process, if we're running
     // from a CLI script. Reload the lease to make sure we have the most
     // up-to-date information. Normally, this has no effect.
     $this->reload();
     $this->setTaskID($task->getID());
     $this->save();
     return $this;
 }
 private function releaseResource(DrydockResource $resource)
 {
     if ($resource->getStatus() != DrydockResourceStatus::STATUS_ACTIVE) {
         // If we had multiple release commands
         // This command is only meaningful to resources in the "Open" state.
         return;
     }
     $viewer = $this->getViewer();
     $drydock_phid = id(new PhabricatorDrydockApplication())->getPHID();
     $resource->openTransaction();
     $resource->setStatus(DrydockResourceStatus::STATUS_RELEASED)->save();
     // TODO: Hold slot locks until destruction?
     DrydockSlotLock::releaseLocks($resource->getPHID());
     $resource->saveTransaction();
     $statuses = array(DrydockLeaseStatus::STATUS_PENDING, DrydockLeaseStatus::STATUS_ACQUIRED, DrydockLeaseStatus::STATUS_ACTIVE);
     $leases = id(new DrydockLeaseQuery())->setViewer($viewer)->withResourcePHIDs(array($resource->getPHID()))->withStatuses($statuses)->execute();
     foreach ($leases as $lease) {
         $command = DrydockCommand::initializeNewCommand($viewer)->setTargetPHID($lease->getPHID())->setAuthorPHID($drydock_phid)->setCommand(DrydockCommand::COMMAND_RELEASE)->save();
         $lease->scheduleUpdate();
     }
     PhabricatorWorker::scheduleTask('DrydockResourceDestroyWorker', array('resourcePHID' => $resource->getPHID()), array('objectPHID' => $resource->getPHID()));
 }
 public function execute(PhutilArgumentParser $args)
 {
     $console = PhutilConsole::getConsole();
     $ids = $args->getArg('id');
     if (!$ids) {
         throw new PhutilArgumentUsageException("Use the '--id' flag to specify one or more messages to resend.");
     }
     $messages = id(new PhabricatorMetaMTAMail())->loadAllWhere('id IN (%Ld)', $ids);
     if ($ids) {
         $ids = array_fuse($ids);
         $missing = array_diff_key($ids, $messages);
         if ($missing) {
             throw new PhutilArgumentUsageException('Some specified messages do not exist: ' . implode(', ', array_keys($missing)));
         }
     }
     foreach ($messages as $message) {
         $message->setStatus(PhabricatorMetaMTAMail::STATUS_QUEUE);
         $message->save();
         $mailer_task = PhabricatorWorker::scheduleTask('PhabricatorMetaMTAWorker', $message->getID(), PhabricatorWorker::PRIORITY_ALERTS);
         $console->writeOut("Queued message #%d for resend.\n", $message->getID());
     }
 }
 private function executeBuildCommand(HarbormasterBuild $build, HarbormasterBuildTransaction $xaction)
 {
     $command = $xaction->getNewValue();
     switch ($command) {
         case HarbormasterBuildCommand::COMMAND_RESTART:
             $issuable = $build->canRestartBuild();
             break;
         case HarbormasterBuildCommand::COMMAND_STOP:
             $issuable = $build->canStopBuild();
             break;
         case HarbormasterBuildCommand::COMMAND_RESUME:
             $issuable = $build->canResumeBuild();
             break;
         default:
             throw new Exception("Unknown command {$command}");
     }
     if (!$issuable) {
         return;
     }
     id(new HarbormasterBuildCommand())->setAuthorPHID($xaction->getAuthorPHID())->setTargetPHID($build->getPHID())->setCommand($command)->save();
     PhabricatorWorker::scheduleTask('HarbormasterBuildWorker', array('buildID' => $build->getID()));
 }
 public function execute(PhutilArgumentParser $args)
 {
     $console = PhutilConsole::getConsole();
     $viewer = $this->getViewer();
     $key = $args->getArg('key');
     if (count($key) < 1) {
         throw new PhutilArgumentUsageException(pht('Specify a story key to republish.'));
     } else {
         if (count($key) > 1) {
             throw new PhutilArgumentUsageException(pht('Specify exactly one story key to republish.'));
         }
     }
     $key = head($key);
     $story = id(new PhabricatorFeedQuery())->setViewer($viewer)->withChronologicalKeys(array($key))->executeOne();
     if (!$story) {
         throw new PhutilArgumentUsageException(pht('No story exists with key "%s"!', $key));
     }
     $console->writeOut("%s\n", pht('Republishing story...'));
     PhabricatorWorker::setRunAllTasksInProcess(true);
     PhabricatorWorker::scheduleTask('FeedPublisherWorker', array('key' => $key));
     $console->writeOut("%s\n", pht('Done.'));
     return 0;
 }
 public function continueBuild()
 {
     $build = $this->getBuild();
     $lock_key = 'harbormaster.build:' . $build->getID();
     $lock = PhabricatorGlobalLock::newLock($lock_key)->lock(15);
     $build->reload();
     $old_status = $build->getBuildStatus();
     try {
         $this->updateBuild($build);
     } catch (Exception $ex) {
         // If any exception is raised, the build is marked as a failure and the
         // exception is re-thrown (this ensures we don't leave builds in an
         // inconsistent state).
         $build->setBuildStatus(HarbormasterBuild::STATUS_ERROR);
         $build->save();
         $lock->unlock();
         $this->releaseAllArtifacts($build);
         throw $ex;
     }
     $lock->unlock();
     // NOTE: We queue new targets after releasing the lock so that in-process
     // execution via `bin/harbormaster` does not reenter the locked region.
     foreach ($this->getNewBuildTargets() as $target) {
         $task = PhabricatorWorker::scheduleTask('HarbormasterTargetWorker', array('targetID' => $target->getID()), array('objectPHID' => $target->getPHID()));
     }
     // If the build changed status, we might need to update the overall status
     // on the buildable.
     $new_status = $build->getBuildStatus();
     if ($new_status != $old_status || $this->shouldForceBuildableUpdate()) {
         $this->updateBuildable($build->getBuildable());
     }
     $this->releaseQueuedArtifacts();
     // If we are no longer building for any reason, release all artifacts.
     if (!$build->isBuilding()) {
         $this->releaseAllArtifacts($build);
     }
 }
 private function insertTask(PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit, $data = array())
 {
     $vcs = $repository->getVersionControlSystem();
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             $class = 'PhabricatorRepositoryGitCommitMessageParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             $class = 'PhabricatorRepositorySvnCommitMessageParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $class = 'PhabricatorRepositoryMercurialCommitMessageParserWorker';
             break;
         default:
             throw new Exception(pht("Unknown repository type '%s'!", $vcs));
     }
     $data['commitID'] = $commit->getID();
     PhabricatorWorker::scheduleTask($class, $data);
 }
 /**
  * Perform an actual lease acquisition on a particular resource.
  *
  * @param DrydockResource Resource to acquire a lease on.
  * @param DrydockLease Lease to acquire.
  * @return void
  * @task lease
  */
 private function acquireLease(DrydockResource $resource, DrydockLease $lease)
 {
     $blueprint = $resource->getBlueprint();
     $blueprint->acquireLease($resource, $lease);
     $this->validateAcquiredLease($blueprint, $resource, $lease);
     // If this lease has been acquired but not activated, queue a task to
     // activate it.
     if ($lease->getStatus() == DrydockLeaseStatus::STATUS_ACQUIRED) {
         PhabricatorWorker::scheduleTask('DrydockLeaseWorker', array('leasePHID' => $lease->getPHID()), array('objectPHID' => $lease->getPHID()));
     }
 }
 private function scheduleTask(array $data = array(), $priority = null)
 {
     return PhabricatorWorker::scheduleTask('PhabricatorTestWorker', $data, array('priority' => $priority));
 }
 public function save()
 {
     if ($this->getID()) {
         return parent::save();
     }
     // NOTE: When mail is sent from CLI scripts that run tasks in-process, we
     // may re-enter this method from within scheduleTask(). The implementation
     // is intended to avoid anything awkward if we end up reentering this
     // method.
     $this->openTransaction();
     // Save to generate a mail ID and PHID.
     $result = parent::save();
     // Write the recipient edges.
     $editor = new PhabricatorEdgeEditor();
     $edge_type = PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST;
     $recipient_phids = array_merge($this->getToPHIDs(), $this->getCcPHIDs());
     $expanded_phids = $this->expandRecipients($recipient_phids);
     $all_phids = array_unique(array_merge($recipient_phids, $expanded_phids));
     foreach ($all_phids as $curr_phid) {
         $editor->addEdge($this->getPHID(), $edge_type, $curr_phid);
     }
     $editor->save();
     // Queue a task to send this mail.
     $mailer_task = PhabricatorWorker::scheduleTask('PhabricatorMetaMTAWorker', $this->getID(), array('priority' => PhabricatorWorker::PRIORITY_ALERTS));
     $this->saveTransaction();
     return $result;
 }
Пример #19
0
 public function applyPlan(HarbormasterBuildPlan $plan, array $parameters, $initiator_phid)
 {
     $viewer = PhabricatorUser::getOmnipotentUser();
     $build = HarbormasterBuild::initializeNewBuild($viewer)->setBuildablePHID($this->getPHID())->setBuildPlanPHID($plan->getPHID())->setBuildParameters($parameters)->setBuildStatus(HarbormasterBuildStatus::STATUS_PENDING);
     if ($initiator_phid) {
         $build->setInitiatorPHID($initiator_phid);
     }
     $auto_key = $plan->getPlanAutoKey();
     if ($auto_key) {
         $build->setPlanAutoKey($auto_key);
     }
     $build->save();
     PhabricatorWorker::scheduleTask('HarbormasterBuildWorker', array('buildID' => $build->getID()), array('objectPHID' => $build->getPHID()));
     return $build;
 }
 public function publish()
 {
     $class = $this->storyType;
     if (!$class) {
         throw new Exception(pht('Call %s before publishing!', 'setStoryType()'));
     }
     if (!class_exists($class)) {
         throw new Exception(pht("Story type must be a valid class name and must subclass %s. " . "'%s' is not a loadable class.", 'PhabricatorFeedStory', $class));
     }
     if (!is_subclass_of($class, 'PhabricatorFeedStory')) {
         throw new Exception(pht("Story type must be a valid class name and must subclass %s. " . "'%s' is not a subclass of %s.", 'PhabricatorFeedStory', $class, 'PhabricatorFeedStory'));
     }
     $chrono_key = $this->generateChronologicalKey();
     $story = new PhabricatorFeedStoryData();
     $story->setStoryType($this->storyType);
     $story->setStoryData($this->storyData);
     $story->setAuthorPHID((string) $this->storyAuthorPHID);
     $story->setChronologicalKey($chrono_key);
     $story->save();
     if ($this->relatedPHIDs) {
         $ref = new PhabricatorFeedStoryReference();
         $sql = array();
         $conn = $ref->establishConnection('w');
         foreach (array_unique($this->relatedPHIDs) as $phid) {
             $sql[] = qsprintf($conn, '(%s, %s)', $phid, $chrono_key);
         }
         queryfx($conn, 'INSERT INTO %T (objectPHID, chronologicalKey) VALUES %Q', $ref->getTableName(), implode(', ', $sql));
     }
     $subscribed_phids = $this->subscribedPHIDs;
     if ($subscribed_phids) {
         $subscribed_phids = $this->filterSubscribedPHIDs($subscribed_phids);
         $this->insertNotifications($chrono_key, $subscribed_phids);
         $this->sendNotification($chrono_key, $subscribed_phids);
     }
     PhabricatorWorker::scheduleTask('FeedPublisherWorker', array('key' => $chrono_key));
     return $story;
 }
 public final function applyTransactions(PhabricatorLiskDAO $object, array $xactions)
 {
     $this->object = $object;
     $this->xactions = $xactions;
     $this->isNewObject = $object->getPHID() === null;
     $this->validateEditParameters($object, $xactions);
     $actor = $this->requireActor();
     // NOTE: Some transaction expansion requires that the edited object be
     // attached.
     foreach ($xactions as $xaction) {
         $xaction->attachObject($object);
         $xaction->attachViewer($actor);
     }
     $xactions = $this->expandTransactions($object, $xactions);
     $xactions = $this->expandSupportTransactions($object, $xactions);
     $xactions = $this->combineTransactions($xactions);
     foreach ($xactions as $xaction) {
         $xaction = $this->populateTransaction($object, $xaction);
     }
     $is_preview = $this->getIsPreview();
     $read_locking = false;
     $transaction_open = false;
     if (!$is_preview) {
         $errors = array();
         $type_map = mgroup($xactions, 'getTransactionType');
         foreach ($this->getTransactionTypes() as $type) {
             $type_xactions = idx($type_map, $type, array());
             $errors[] = $this->validateTransaction($object, $type, $type_xactions);
         }
         $errors[] = $this->validateAllTransactions($object, $xactions);
         $errors = array_mergev($errors);
         $continue_on_missing = $this->getContinueOnMissingFields();
         foreach ($errors as $key => $error) {
             if ($continue_on_missing && $error->getIsMissingFieldError()) {
                 unset($errors[$key]);
             }
         }
         if ($errors) {
             throw new PhabricatorApplicationTransactionValidationException($errors);
         }
         $this->willApplyTransactions($object, $xactions);
         if ($object->getID()) {
             foreach ($xactions as $xaction) {
                 // If any of the transactions require a read lock, hold one and
                 // reload the object. We need to do this fairly early so that the
                 // call to `adjustTransactionValues()` (which populates old values)
                 // is based on the synchronized state of the object, which may differ
                 // from the state when it was originally loaded.
                 if ($this->shouldReadLock($object, $xaction)) {
                     $object->openTransaction();
                     $object->beginReadLocking();
                     $transaction_open = true;
                     $read_locking = true;
                     $object->reload();
                     break;
                 }
             }
         }
         if ($this->shouldApplyInitialEffects($object, $xactions)) {
             if (!$transaction_open) {
                 $object->openTransaction();
                 $transaction_open = true;
             }
         }
     }
     if ($this->shouldApplyInitialEffects($object, $xactions)) {
         $this->applyInitialEffects($object, $xactions);
     }
     foreach ($xactions as $xaction) {
         $this->adjustTransactionValues($object, $xaction);
     }
     try {
         $xactions = $this->filterTransactions($object, $xactions);
     } catch (Exception $ex) {
         if ($read_locking) {
             $object->endReadLocking();
         }
         if ($transaction_open) {
             $object->killTransaction();
         }
         throw $ex;
     }
     // TODO: Once everything is on EditEngine, just use getIsNewObject() to
     // figure this out instead.
     $mark_as_create = false;
     $create_type = PhabricatorTransactions::TYPE_CREATE;
     foreach ($xactions as $xaction) {
         if ($xaction->getTransactionType() == $create_type) {
             $mark_as_create = true;
         }
     }
     if ($mark_as_create) {
         foreach ($xactions as $xaction) {
             $xaction->setIsCreateTransaction(true);
         }
     }
     // Now that we've merged, filtered, and combined transactions, check for
     // required capabilities.
     foreach ($xactions as $xaction) {
         $this->requireCapabilities($object, $xaction);
     }
     $xactions = $this->sortTransactions($xactions);
     $file_phids = $this->extractFilePHIDs($object, $xactions);
     if ($is_preview) {
         $this->loadHandles($xactions);
         return $xactions;
     }
     $comment_editor = id(new PhabricatorApplicationTransactionCommentEditor())->setActor($actor)->setActingAsPHID($this->getActingAsPHID())->setContentSource($this->getContentSource());
     if (!$transaction_open) {
         $object->openTransaction();
     }
     try {
         foreach ($xactions as $xaction) {
             $this->applyInternalEffects($object, $xaction);
         }
         $xactions = $this->didApplyInternalEffects($object, $xactions);
         try {
             $object->save();
         } catch (AphrontDuplicateKeyQueryException $ex) {
             // This callback has an opportunity to throw a better exception,
             // so execution may end here.
             $this->didCatchDuplicateKeyException($object, $xactions, $ex);
             throw $ex;
         }
         foreach ($xactions as $xaction) {
             $xaction->setObjectPHID($object->getPHID());
             if ($xaction->getComment()) {
                 $xaction->setPHID($xaction->generatePHID());
                 $comment_editor->applyEdit($xaction, $xaction->getComment());
             } else {
                 $xaction->save();
             }
         }
         if ($file_phids) {
             $this->attachFiles($object, $file_phids);
         }
         foreach ($xactions as $xaction) {
             $this->applyExternalEffects($object, $xaction);
         }
         $xactions = $this->applyFinalEffects($object, $xactions);
         if ($read_locking) {
             $object->endReadLocking();
             $read_locking = false;
         }
         $object->saveTransaction();
     } catch (Exception $ex) {
         $object->killTransaction();
         throw $ex;
     }
     // Now that we've completely applied the core transaction set, try to apply
     // Herald rules. Herald rules are allowed to either take direct actions on
     // the database (like writing flags), or take indirect actions (like saving
     // some targets for CC when we generate mail a little later), or return
     // transactions which we'll apply normally using another Editor.
     // First, check if *this* is a sub-editor which is itself applying Herald
     // rules: if it is, stop working and return so we don't descend into
     // madness.
     // Otherwise, we're not a Herald editor, so process Herald rules (possibly
     // using a Herald editor to apply resulting transactions) and then send out
     // mail, notifications, and feed updates about everything.
     if ($this->getIsHeraldEditor()) {
         // We are the Herald editor, so stop work here and return the updated
         // transactions.
         return $xactions;
     } else {
         if ($this->getIsInverseEdgeEditor()) {
             // If we're applying inverse edge transactions, don't trigger Herald.
             // From a product perspective, the current set of inverse edges (most
             // often, mentions) aren't things users would expect to trigger Herald.
             // From a technical perspective, objects loaded by the inverse editor may
             // not have enough data to execute rules. At least for now, just stop
             // Herald from executing when applying inverse edges.
         } else {
             if ($this->shouldApplyHeraldRules($object, $xactions)) {
                 // We are not the Herald editor, so try to apply Herald rules.
                 $herald_xactions = $this->applyHeraldRules($object, $xactions);
                 if ($herald_xactions) {
                     $xscript_id = $this->getHeraldTranscript()->getID();
                     foreach ($herald_xactions as $herald_xaction) {
                         // Don't set a transcript ID if this is a transaction from another
                         // application or source, like Owners.
                         if ($herald_xaction->getAuthorPHID()) {
                             continue;
                         }
                         $herald_xaction->setMetadataValue('herald:transcriptID', $xscript_id);
                     }
                     // NOTE: We're acting as the omnipotent user because rules deal with
                     // their own policy issues. We use a synthetic author PHID (the
                     // Herald application) as the author of record, so that transactions
                     // will render in a reasonable way ("Herald assigned this task ...").
                     $herald_actor = PhabricatorUser::getOmnipotentUser();
                     $herald_phid = id(new PhabricatorHeraldApplication())->getPHID();
                     // TODO: It would be nice to give transactions a more specific source
                     // which points at the rule which generated them. You can figure this
                     // out from transcripts, but it would be cleaner if you didn't have to.
                     $herald_source = PhabricatorContentSource::newForSource(PhabricatorHeraldContentSource::SOURCECONST);
                     $herald_editor = newv(get_class($this), array())->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->setParentMessageID($this->getParentMessageID())->setIsHeraldEditor(true)->setActor($herald_actor)->setActingAsPHID($herald_phid)->setContentSource($herald_source);
                     $herald_xactions = $herald_editor->applyTransactions($object, $herald_xactions);
                     // Merge the new transactions into the transaction list: we want to
                     // send email and publish feed stories about them, too.
                     $xactions = array_merge($xactions, $herald_xactions);
                 }
                 // If Herald did not generate transactions, we may still need to handle
                 // "Send an Email" rules.
                 $adapter = $this->getHeraldAdapter();
                 $this->heraldEmailPHIDs = $adapter->getEmailPHIDs();
                 $this->heraldForcedEmailPHIDs = $adapter->getForcedEmailPHIDs();
             }
         }
     }
     $this->didApplyTransactions($xactions);
     if ($object instanceof PhabricatorCustomFieldInterface) {
         // Maybe this makes more sense to move into the search index itself? For
         // now I'm putting it here since I think we might end up with things that
         // need it to be up to date once the next page loads, but if we don't go
         // there we could move it into search once search moves to the daemons.
         // It now happens in the search indexer as well, but the search indexer is
         // always daemonized, so the logic above still potentially holds. We could
         // possibly get rid of this. The major motivation for putting it in the
         // indexer was to enable reindexing to work.
         $fields = PhabricatorCustomField::getObjectFields($object, PhabricatorCustomField::ROLE_APPLICATIONSEARCH);
         $fields->readFieldsFromStorage($object);
         $fields->rebuildIndexes($object);
     }
     $herald_xscript = $this->getHeraldTranscript();
     if ($herald_xscript) {
         $herald_header = $herald_xscript->getXHeraldRulesHeader();
         $herald_header = HeraldTranscript::saveXHeraldRulesHeader($object->getPHID(), $herald_header);
     } else {
         $herald_header = HeraldTranscript::loadXHeraldRulesHeader($object->getPHID());
     }
     $this->heraldHeader = $herald_header;
     // We're going to compute some of the data we'll use to publish these
     // transactions here, before queueing a worker.
     //
     // Primarily, this is more correct: we want to publish the object as it
     // exists right now. The worker may not execute for some time, and we want
     // to use the current To/CC list, not respect any changes which may occur
     // between now and when the worker executes.
     //
     // As a secondary benefit, this tends to reduce the amount of state that
     // Editors need to pass into workers.
     $object = $this->willPublish($object, $xactions);
     if (!$this->getDisableEmail()) {
         if ($this->shouldSendMail($object, $xactions)) {
             $this->mailToPHIDs = $this->getMailTo($object);
             $this->mailCCPHIDs = $this->getMailCC($object);
         }
     }
     if ($this->shouldPublishFeedStory($object, $xactions)) {
         $this->feedRelatedPHIDs = $this->getFeedRelatedPHIDs($object, $xactions);
         $this->feedNotifyPHIDs = $this->getFeedNotifyPHIDs($object, $xactions);
     }
     PhabricatorWorker::scheduleTask('PhabricatorApplicationTransactionPublishWorker', array('objectPHID' => $object->getPHID(), 'actorPHID' => $this->getActingAsPHID(), 'xactionPHIDs' => mpull($xactions, 'getPHID'), 'state' => $this->getWorkerState()), array('objectPHID' => $object->getPHID(), 'priority' => PhabricatorWorker::PRIORITY_ALERTS));
     return $xactions;
 }
 /**
  * Perform an actual resource allocation with a particular blueprint.
  *
  * @param DrydockBlueprint The blueprint to allocate a resource from.
  * @param DrydockLease Requested lease.
  * @return DrydockResource Allocated resource.
  * @task allocator
  */
 private function allocateResource(DrydockBlueprint $blueprint, DrydockLease $lease)
 {
     $resource = $blueprint->allocateResource($lease);
     $this->validateAllocatedResource($blueprint, $resource, $lease);
     // If this resource was allocated as a pending resource, queue a task to
     // activate it.
     if ($resource->getStatus() == DrydockResourceStatus::STATUS_PENDING) {
         PhabricatorWorker::scheduleTask('DrydockResourceUpdateWorker', array('resourcePHID' => $resource->getPHID()), array('objectPHID' => $resource->getPHID()));
     }
     return $resource;
 }
Пример #23
0
 public function scheduleUpdate()
 {
     PhabricatorWorker::scheduleTask('NuanceItemUpdateWorker', array('itemPHID' => $this->getPHID()), array('objectPHID' => $this->getPHID()));
 }
 public function execute()
 {
     $ref_updates = $this->findRefUpdates();
     $all_updates = $ref_updates;
     $caught = null;
     try {
         try {
             $this->rejectDangerousChanges($ref_updates);
         } catch (DiffusionCommitHookRejectException $ex) {
             // If we're rejecting dangerous changes, flag everything that we've
             // seen as rejected so it's clear that none of it was accepted.
             $this->rejectCode = PhabricatorRepositoryPushLog::REJECT_DANGEROUS;
             throw $ex;
         }
         $this->applyHeraldRefRules($ref_updates, $all_updates);
         $content_updates = $this->findContentUpdates($ref_updates);
         $all_updates = array_merge($all_updates, $content_updates);
         $this->applyHeraldContentRules($content_updates, $all_updates);
         // Run custom scripts in `hook.d/` directories.
         $this->applyCustomHooks($all_updates);
         // If we make it this far, we're accepting these changes. Mark all the
         // logs as accepted.
         $this->rejectCode = PhabricatorRepositoryPushLog::REJECT_ACCEPT;
     } catch (Exception $ex) {
         // We'll throw this again in a minute, but we want to save all the logs
         // first.
         $caught = $ex;
     }
     // Save all the logs no matter what the outcome was.
     $event = $this->newPushEvent();
     $event->setRejectCode($this->rejectCode);
     $event->setRejectDetails($this->rejectDetails);
     $event->openTransaction();
     $event->save();
     foreach ($all_updates as $update) {
         $update->setPushEventPHID($event->getPHID());
         $update->save();
     }
     $event->saveTransaction();
     if ($caught) {
         throw $caught;
     }
     // If this went through cleanly, detect pushes which are actually imports
     // of an existing repository rather than an addition of new commits. If
     // this push is importing a bunch of stuff, set the importing flag on
     // the repository. It will be cleared once we fully process everything.
     if ($this->isInitialImport($all_updates)) {
         $repository = $this->getRepository();
         $repository->markImporting();
     }
     if ($this->emailPHIDs) {
         // If Herald rules triggered email to users, queue a worker to send the
         // mail. We do this out-of-process so that we block pushes as briefly
         // as possible.
         // (We do need to pull some commit info here because the commit objects
         // may not exist yet when this worker runs, which could be immediately.)
         PhabricatorWorker::scheduleTask('PhabricatorRepositoryPushMailWorker', array('eventPHID' => $event->getPHID(), 'emailPHIDs' => array_values($this->emailPHIDs), 'info' => $this->loadCommitInfoForWorker($all_updates)), array('priority' => PhabricatorWorker::PRIORITY_ALERTS));
     }
     return 0;
 }
Пример #25
0
 public function scheduleUpdate($epoch = null)
 {
     PhabricatorWorker::scheduleTask('DrydockLeaseUpdateWorker', array('leasePHID' => $this->getPHID(), 'isExpireTask' => $epoch !== null), array('objectPHID' => $this->getPHID(), 'delayUntil' => $epoch));
 }
 /**
  * Mark a list of commits as closeable, and queue workers for those commits
  * which don't already have the flag.
  */
 private function setCloseFlagOnCommits(array $identifiers)
 {
     $repository = $this->getRepository();
     $commit_table = new PhabricatorRepositoryCommit();
     $conn_w = $commit_table->establishConnection('w');
     $vcs = $repository->getVersionControlSystem();
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
             $class = 'PhabricatorRepositoryGitCommitMessageParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             $class = 'PhabricatorRepositorySvnCommitMessageParserWorker';
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $class = 'PhabricatorRepositoryMercurialCommitMessageParserWorker';
             break;
         default:
             throw new Exception("Unknown repository type '{$vcs}'!");
     }
     $all_commits = queryfx_all($conn_w, 'SELECT id, commitIdentifier, importStatus FROM %T
     WHERE repositoryID = %d AND commitIdentifier IN (%Ls)', $commit_table->getTableName(), $repository->getID(), $identifiers);
     $closeable_flag = PhabricatorRepositoryCommit::IMPORTED_CLOSEABLE;
     $all_commits = ipull($all_commits, null, 'commitIdentifier');
     foreach ($identifiers as $identifier) {
         $row = idx($all_commits, $identifier);
         if (!$row) {
             throw new Exception(pht('Commit "%s" has not been discovered yet! Run discovery before ' . 'updating refs.', $identifier));
         }
         if (!($row['importStatus'] & $closeable_flag)) {
             queryfx($conn_w, 'UPDATE %T SET importStatus = (importStatus | %d) WHERE id = %d', $commit_table->getTableName(), $closeable_flag, $row['id']);
             $data = array('commitID' => $row['id'], 'only' => true);
             PhabricatorWorker::scheduleTask($class, $data);
         }
     }
 }
 /**
  * Convenience function to handle sending an SMS.
  */
 public static function sendSMS(array $to_numbers, $body)
 {
     PhabricatorWorker::scheduleTask('PhabricatorSMSDemultiplexWorker', array('toNumbers' => $to_numbers, 'body' => $body), array('priority' => PhabricatorWorker::PRIORITY_ALERTS));
 }
Пример #28
0
            }
            break;
    }
    if ($reparse_herald) {
        $classes[] = 'PhabricatorRepositoryCommitHeraldWorker';
    }
    if ($reparse_owners) {
        $classes[] = 'PhabricatorRepositoryCommitOwnersWorker';
    }
    if ($reparse_harbormaster) {
        $classes[] = 'HarbormasterRunnerWorker';
    }
    $spec = array('commitID' => $commit->getID(), 'only' => true);
    if ($all_from_repo && !$force_local) {
        foreach ($classes as $class) {
            PhabricatorWorker::scheduleTask($class, $spec, PhabricatorWorker::PRIORITY_IMPORT);
        }
    } else {
        foreach ($classes as $class) {
            $worker = newv($class, array($spec));
            $worker->executeTask();
        }
    }
    $progress->update(1);
}
$progress->done();
function usage($message)
{
    echo phutil_console_format('**Usage Exception:** ' . $message . "\n" . "Use __--help__ to display full help\n");
    exit(1);
}
 public function scheduleUpdate()
 {
     PhabricatorWorker::scheduleTask('DrydockRepositoryOperationUpdateWorker', array('operationPHID' => $this->getPHID()), array('objectPHID' => $this->getPHID(), 'priority' => PhabricatorWorker::PRIORITY_ALERTS));
 }
Пример #30
0
 public function scheduleUpdate()
 {
     PhabricatorWorker::scheduleTask('DrydockResourceUpdateWorker', array('resourcePHID' => $this->getPHID()), array('objectPHID' => $this->getPHID()));
 }