diff --git a/src/applications/daemon/controller/PhabricatorDaemonBulkJobViewController.php b/src/applications/daemon/controller/PhabricatorDaemonBulkJobViewController.php index 6fc3af724e..f32892cf4c 100644 --- a/src/applications/daemon/controller/PhabricatorDaemonBulkJobViewController.php +++ b/src/applications/daemon/controller/PhabricatorDaemonBulkJobViewController.php @@ -1,83 +1,89 @@ getViewer(); $job = id(new PhabricatorWorkerBulkJobQuery()) ->setViewer($viewer) ->withIDs(array($request->getURIData('id'))) ->executeOne(); if (!$job) { return new Aphront404Response(); } $title = pht('Bulk Job %d', $job->getID()); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Bulk Jobs'), '/daemon/bulk/'); $crumbs->addTextCrumb($title); $properties = $this->renderProperties($job); $actions = $this->renderActions($job); $properties->setActionList($actions); $box = id(new PHUIObjectBoxView()) ->setHeaderText($title) ->addPropertyList($properties); $timeline = $this->buildTransactionTimeline( $job, new PhabricatorWorkerBulkJobTransactionQuery()); $timeline->setShouldTerminate(true); return $this->buildApplicationPage( array( $crumbs, $box, $timeline, ), array( 'title' => $title, )); } private function renderProperties(PhabricatorWorkerBulkJob $job) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($job); $view->addProperty( pht('Author'), $viewer->renderHandle($job->getAuthorPHID())); $view->addProperty(pht('Status'), $job->getStatusName()); return $view; } private function renderActions(PhabricatorWorkerBulkJob $job) { $viewer = $this->getViewer(); $actions = id(new PhabricatorActionListView()) ->setUser($viewer) ->setObject($job); + if ($job->isConfirming()) { + $continue_uri = $job->getMonitorURI(); + } else { + $continue_uri = $job->getDoneURI(); + } + $actions->addAction( id(new PhabricatorActionView()) - ->setHref($job->getDoneURI()) + ->setHref($continue_uri) ->setIcon('fa-arrow-circle-o-right') ->setName(pht('Continue'))); return $actions; } } diff --git a/src/infrastructure/daemon/workers/storage/PhabricatorWorkerBulkJob.php b/src/infrastructure/daemon/workers/storage/PhabricatorWorkerBulkJob.php index 7eed0240eb..20d981c576 100644 --- a/src/infrastructure/daemon/workers/storage/PhabricatorWorkerBulkJob.php +++ b/src/infrastructure/daemon/workers/storage/PhabricatorWorkerBulkJob.php @@ -1,272 +1,276 @@ true, self::CONFIG_SERIALIZATION => array( 'parameters' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( 'jobTypeKey' => 'text32', 'status' => 'text32', 'size' => 'uint32', ), self::CONFIG_KEY_SCHEMA => array( 'key_type' => array( 'columns' => array('jobTypeKey'), ), 'key_author' => array( 'columns' => array('authorPHID'), ), 'key_status' => array( 'columns' => array('status'), ), ), ) + parent::getConfiguration(); } public static function initializeNewJob( PhabricatorUser $actor, PhabricatorWorkerBulkJobType $type, array $parameters) { $job = id(new PhabricatorWorkerBulkJob()) ->setAuthorPHID($actor->getPHID()) ->setJobTypeKey($type->getBulkJobTypeKey()) ->setParameters($parameters) ->attachJobImplementation($type); $job->setSize($job->computeSize()); return $job; } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorWorkerBulkJobPHIDType::TYPECONST); } public function getMonitorURI() { return '/daemon/bulk/monitor/'.$this->getID().'/'; } public function getManageURI() { return '/daemon/bulk/view/'.$this->getID().'/'; } public function getParameter($key, $default = null) { return idx($this->parameters, $key, $default); } public function setParameter($key, $value) { $this->parameters[$key] = $value; return $this; } public function loadTaskStatusCounts() { $table = new PhabricatorWorkerBulkTask(); $conn_r = $table->establishConnection('r'); $rows = queryfx_all( $conn_r, 'SELECT status, COUNT(*) N FROM %T WHERE bulkJobPHID = %s GROUP BY status', $table->getTableName(), $this->getPHID()); return ipull($rows, 'N', 'status'); } public function newContentSource() { return PhabricatorContentSource::newForSource( PhabricatorContentSource::SOURCE_BULK, array( 'jobID' => $this->getID(), )); } public function getStatusIcon() { $map = array( self::STATUS_CONFIRM => 'fa-question', self::STATUS_WAITING => 'fa-clock-o', self::STATUS_RUNNING => 'fa-clock-o', self::STATUS_COMPLETE => 'fa-check grey', ); return idx($map, $this->getStatus(), 'none'); } public function getStatusName() { $map = array( self::STATUS_CONFIRM => pht('Confirming'), self::STATUS_WAITING => pht('Waiting'), self::STATUS_RUNNING => pht('Running'), self::STATUS_COMPLETE => pht('Complete'), ); return idx($map, $this->getStatus(), $this->getStatus()); } + public function isConfirming() { + return ($this->getStatus() == self::STATUS_CONFIRM); + } + /* -( Job Implementation )------------------------------------------------- */ protected function getJobImplementation() { return $this->assertAttached($this->jobImplementation); } public function attachJobImplementation(PhabricatorWorkerBulkJobType $type) { $this->jobImplementation = $type; return $this; } private function computeSize() { return $this->getJobImplementation()->getJobSize($this); } public function getCancelURI() { return $this->getJobImplementation()->getCancelURI($this); } public function getDoneURI() { return $this->getJobImplementation()->getDoneURI($this); } public function getDescriptionForConfirm() { return $this->getJobImplementation()->getDescriptionForConfirm($this); } public function createTasks() { return $this->getJobImplementation()->createTasks($this); } public function runTask( PhabricatorUser $actor, PhabricatorWorkerBulkTask $task) { return $this->getJobImplementation()->runTask($actor, $this, $task); } public function getJobName() { return $this->getJobImplementation()->getJobName($this); } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return PhabricatorPolicies::getMostOpenPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return $this->getAuthorPHID(); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return false; } public function describeAutomaticCapability($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_EDIT: return pht('Only the owner of a bulk job can edit it.'); default: return null; } } /* -( PhabricatorSubscribableInterface )----------------------------------- */ public function isAutomaticallySubscribed($phid) { return false; } public function shouldShowSubscribersProperty() { return true; } public function shouldAllowSubscription($phid) { return true; } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PhabricatorWorkerBulkJobEditor(); } public function getApplicationTransactionObject() { return $this; } public function getApplicationTransactionTemplate() { return new PhabricatorWorkerBulkJobTransaction(); } public function willRenderTimeline( PhabricatorApplicationTransactionView $timeline, AphrontRequest $request) { return $timeline; } /* -( PhabricatorDestructibleInterface )----------------------------------- */ public function destroyObjectPermanently( PhabricatorDestructionEngine $engine) { $this->openTransaction(); // We're only removing the actual task objects. This may leave stranded // workers in the queue itself, but they'll just flush out automatically // when they can't load bulk job data. $task_table = new PhabricatorWorkerBulkTask(); $conn_w = $task_table->establishConnection('w'); queryfx( $conn_w, 'DELETE FROM %T WHERE bulkJobPHID = %s', $task_table->getPHID(), $this->getPHID()); $this->delete(); $this->saveTransaction(); } }