diff --git a/src/infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php b/src/infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php index be2408e54a..01fa18b188 100644 --- a/src/infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php +++ b/src/infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php @@ -1,58 +1,84 @@ 'id', 'param' => 'id', 'repeat' => true, 'help' => pht('Select one or more tasks by ID.'), ), + array( + 'name' => 'class', + 'param' => 'name', + 'help' => pht('Select all tasks of a given class.'), + ), ); } protected function loadTasks(PhutilArgumentParser $args) { $ids = $args->getArg('id'); - if (!$ids) { + $class = $args->getArg('class'); + + if (!$ids && !$class) { throw new PhutilArgumentUsageException( - pht('Use --id to select tasks by ID.')); + pht('Use --id or --class to select tasks.')); + } if ($ids && $class) { + throw new PhutilArgumentUsageException( + pht('Use one of --id or --class to select tasks, but not both.')); } - $active_tasks = id(new PhabricatorWorkerActiveTask())->loadAllWhere( - 'id IN (%Ls)', - $ids); - $archive_tasks = id(new PhabricatorWorkerArchiveTaskQuery()) - ->withIDs($ids) - ->execute(); + if ($ids) { + $active_tasks = id(new PhabricatorWorkerActiveTask())->loadAllWhere( + 'id IN (%Ls)', + $ids); + $archive_tasks = id(new PhabricatorWorkerArchiveTaskQuery()) + ->withIDs($ids) + ->execute(); + } else { + $active_tasks = id(new PhabricatorWorkerActiveTask())->loadAllWhere( + 'taskClass IN (%Ls)', + array($class)); + $archive_tasks = id(new PhabricatorWorkerArchiveTaskQuery()) + ->withClassNames(array($class)) + ->execute(); + } $tasks = mpull($active_tasks, null, 'getID') + mpull($archive_tasks, null, 'getID'); - foreach ($ids as $id) { - if (empty($tasks[$id])) { + if ($ids) { + foreach ($ids as $id) { + if (empty($tasks[$id])) { + throw new PhutilArgumentUsageException( + pht('No task exists with id "%s"!', $id)); + } + } + } else { + if (!$tasks) { throw new PhutilArgumentUsageException( - pht('No task exists with id "%s"!', $id)); + pht('No task exists with class "%s"!', $class)); } } // When we lock tasks properly, this gets populated as a side effect. Just // fake it when doing manual CLI stuff. This makes sure CLI yields have // their expires times set properly. foreach ($tasks as $task) { if ($task instanceof PhabricatorWorkerActiveTask) { $task->setServerTime(PhabricatorTime::getNow()); } } return $tasks; } protected function describeTask(PhabricatorWorkerTask $task) { return pht('Task %d (%s)', $task->getID(), $task->getTaskClass()); } } diff --git a/src/infrastructure/daemon/workers/query/PhabricatorWorkerArchiveTaskQuery.php b/src/infrastructure/daemon/workers/query/PhabricatorWorkerArchiveTaskQuery.php index b0aa6addd3..69abac27b0 100644 --- a/src/infrastructure/daemon/workers/query/PhabricatorWorkerArchiveTaskQuery.php +++ b/src/infrastructure/daemon/workers/query/PhabricatorWorkerArchiveTaskQuery.php @@ -1,107 +1,120 @@ ids = $ids; return $this; } public function withDateModifiedSince($timestamp) { $this->dateModifiedSince = $timestamp; return $this; } public function withDateCreatedBefore($timestamp) { $this->dateCreatedBefore = $timestamp; return $this; } public function withObjectPHIDs(array $phids) { $this->objectPHIDs = $phids; return $this; } + public function withClassNames(array $names) { + $this->classNames = $names; + return $this; + } + public function setLimit($limit) { $this->limit = $limit; return $this; } public function execute() { $task_table = new PhabricatorWorkerArchiveTask(); $conn_r = $task_table->establishConnection('r'); $rows = queryfx_all( $conn_r, 'SELECT * FROM %T %Q %Q %Q', $task_table->getTableName(), $this->buildWhereClause($conn_r), $this->buildOrderClause($conn_r), $this->buildLimitClause($conn_r)); return $task_table->loadAllFromArray($rows); } protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { $where = array(); if ($this->ids !== null) { $where[] = qsprintf( $conn_r, 'id in (%Ld)', $this->ids); } if ($this->objectPHIDs !== null) { $where[] = qsprintf( $conn_r, 'objectPHID IN (%Ls)', $this->objectPHIDs); } - if ($this->dateModifiedSince) { + if ($this->dateModifiedSince !== null) { $where[] = qsprintf( $conn_r, 'dateModified > %d', $this->dateModifiedSince); } - if ($this->dateCreatedBefore) { + if ($this->dateCreatedBefore !== null) { $where[] = qsprintf( $conn_r, 'dateCreated < %d', $this->dateCreatedBefore); } + if ($this->classNames !== null) { + $where[] = qsprintf( + $conn_r, + 'taskClass IN (%Ls)', + $this->classNames); + } + return $this->formatWhereClause($where); } private function buildOrderClause(AphrontDatabaseConnection $conn_r) { // NOTE: The garbage collector executes this query with a date constraint, // and the query is inefficient if we don't use the same key for ordering. // See T9808 for discussion. if ($this->dateCreatedBefore) { return qsprintf($conn_r, 'ORDER BY dateCreated DESC, id DESC'); } else { return qsprintf($conn_r, 'ORDER BY id DESC'); } } private function buildLimitClause(AphrontDatabaseConnection $conn_r) { $clause = ''; if ($this->limit) { $clause = qsprintf($conn_r, 'LIMIT %d', $this->limit); } return $clause; } }