Skip to content

Commit ba4ebf2

Browse files
author
epriestley
committed
Allow archived tasks to be queried by object PHID and order by id
Summary: Ref T5402. Test Plan: - Queried archived tasks. - Grepped for use sites and verified no other callsites are order-sensitive. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5402 Differential Revision: https://secure.phabricator.com/D11089
1 parent 12c7c39 commit ba4ebf2

File tree

5 files changed

+83
-10
lines changed

5 files changed

+83
-10
lines changed

src/applications/daemon/controller/PhabricatorDaemonConsoleController.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,11 @@ public function processRequest() {
131131
$daemon_panel->appendChild($daemon_table);
132132

133133

134-
$tasks = id(new PhabricatorWorkerActiveTask())->loadAllWhere(
135-
'leaseOwner IS NOT NULL');
134+
$tasks = id(new PhabricatorWorkerLeaseQuery())
135+
->setSkipLease(true)
136+
->withLeasedTasks(true)
137+
->setLimit(100)
138+
->execute();
136139

137140
$tasks_table = id(new PhabricatorDaemonTasksTableView())
138141
->setTasks($tasks)

src/infrastructure/daemon/workers/query/PhabricatorWorkerArchiveTaskQuery.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ final class PhabricatorWorkerArchiveTaskQuery
66
private $ids;
77
private $dateModifiedSince;
88
private $dateCreatedBefore;
9+
private $objectPHIDs;
910
private $limit;
1011

1112
public function withIDs(array $ids) {
@@ -23,20 +24,24 @@ public function withDateCreatedBefore($timestamp) {
2324
return $this;
2425
}
2526

27+
public function withObjectPHIDs(array $phids) {
28+
$this->objectPHIDs = $phids;
29+
return $this;
30+
}
31+
2632
public function setLimit($limit) {
2733
$this->limit = $limit;
2834
return $this;
2935
}
3036

3137
public function execute() {
32-
3338
$task_table = new PhabricatorWorkerArchiveTask();
3439

3540
$conn_r = $task_table->establishConnection('r');
3641

3742
$rows = queryfx_all(
3843
$conn_r,
39-
'SELECT * FROM %T %Q %Q',
44+
'SELECT * FROM %T %Q ORDER BY id DESC %Q',
4045
$task_table->getTableName(),
4146
$this->buildWhereClause($conn_r),
4247
$this->buildLimitClause($conn_r));
@@ -54,6 +59,13 @@ private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
5459
$this->ids);
5560
}
5661

62+
if ($this->objectPHIDs !== null) {
63+
$where[] = qsprintf(
64+
$conn_r,
65+
'objectPHID IN (%Ls)',
66+
$this->objectPHIDs);
67+
}
68+
5769
if ($this->dateModifiedSince) {
5870
$where[] = qsprintf(
5971
$conn_r,

src/infrastructure/daemon/workers/query/PhabricatorWorkerLeaseQuery.php

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
*/
66
final class PhabricatorWorkerLeaseQuery extends PhabricatorQuery {
77

8+
const PHASE_LEASED = 'leased';
89
const PHASE_UNLEASED = 'unleased';
910
const PHASE_EXPIRED = 'expired';
1011

1112
private $ids;
1213
private $objectPHIDs;
1314
private $limit;
1415
private $skipLease;
16+
private $leased = false;
1517

1618
public static function getDefaultWaitBeforeRetry() {
1719
return phutil_units('5 minutes in seconds');
@@ -45,14 +47,44 @@ public function withObjectPHIDs(array $phids) {
4547
return $this;
4648
}
4749

50+
/**
51+
* Select only leased tasks, only unleased tasks, or both types of task.
52+
*
53+
* By default, queries select only unleased tasks (equivalent to passing
54+
* `false` to this method). You can pass `true` to select only leased tasks,
55+
* or `null` to ignore the lease status of tasks.
56+
*
57+
* If your result set potentially includes leased tasks, you must disable
58+
* leasing using @{method:setSkipLease}. These options are intended for use
59+
* when displaying task status information.
60+
*
61+
* @param mixed `true` to select only leased tasks, `false` to select only
62+
* unleased tasks (default), or `null` to select both.
63+
* @return this
64+
*/
65+
public function withLeasedTasks($leased) {
66+
$this->leased = $leased;
67+
return $this;
68+
}
69+
4870
public function setLimit($limit) {
4971
$this->limit = $limit;
5072
return $this;
5173
}
5274

5375
public function execute() {
5476
if (!$this->limit) {
55-
throw new Exception('You must setLimit() when leasing tasks.');
77+
throw new Exception(
78+
pht('You must setLimit() when leasing tasks.'));
79+
}
80+
81+
if ($this->leased !== false) {
82+
if (!$this->skipLease) {
83+
throw new Exception(
84+
pht(
85+
'If you potentially select leased tasks using withLeasedTasks(), '.
86+
'you MUST disable lease acquisition by calling setSkipLease().'));
87+
}
5688
}
5789

5890
$task_table = new PhabricatorWorkerActiveTask();
@@ -65,10 +97,16 @@ public function execute() {
6597
// find enough tasks, try tasks with expired leases (i.e., tasks which have
6698
// previously failed).
6799

68-
$phases = array(
69-
self::PHASE_UNLEASED,
70-
self::PHASE_EXPIRED,
71-
);
100+
// If we're selecting leased tasks, look for them first.
101+
102+
$phases = array();
103+
if ($this->leased !== false) {
104+
$phases[] = self::PHASE_LEASED;
105+
}
106+
if ($this->leased !== true) {
107+
$phases[] = self::PHASE_UNLEASED;
108+
$phases[] = self::PHASE_EXPIRED;
109+
}
72110
$limit = $this->limit;
73111

74112
$leased = 0;
@@ -160,13 +198,22 @@ public function execute() {
160198
$tasks[$row['id']]->setData($task_data);
161199
}
162200

201+
if ($this->skipLease) {
202+
// Reorder rows into the original phase order if this is a status query.
203+
$tasks = array_select_keys($tasks, $task_ids);
204+
}
205+
163206
return $tasks;
164207
}
165208

166209
private function buildWhereClause(AphrontDatabaseConnection $conn_w, $phase) {
167210
$where = array();
168211

169212
switch ($phase) {
213+
case self::PHASE_LEASED:
214+
$where[] = 'leaseOwner IS NOT NULL';
215+
$where[] = 'leaseExpires >= UNIX_TIMESTAMP()';
216+
break;
170217
case self::PHASE_UNLEASED:
171218
$where[] = 'leaseOwner IS NULL';
172219
break;
@@ -177,7 +224,7 @@ private function buildWhereClause(AphrontDatabaseConnection $conn_w, $phase) {
177224
throw new Exception("Unknown phase '{$phase}'!");
178225
}
179226

180-
if ($this->ids) {
227+
if ($this->ids !== null) {
181228
$where[] = qsprintf($conn_w, 'id IN (%Ld)', $this->ids);
182229
}
183230

@@ -199,6 +246,11 @@ private function buildUpdateWhereClause(
199246
// `IN (NULL)` doesn't match NULL.
200247

201248
switch ($phase) {
249+
case self::PHASE_LEASED:
250+
throw new Exception(
251+
pht(
252+
'Trying to lease tasks selected in the leased phase! This is '.
253+
'intended to be imposssible.'));
202254
case self::PHASE_UNLEASED:
203255
$where[] = qsprintf($conn_w, 'leaseOwner IS NULL');
204256
$where[] = qsprintf($conn_w, 'id IN (%Ld)', ipull($rows, 'id'));
@@ -223,6 +275,10 @@ private function buildUpdateWhereClause(
223275

224276
private function buildOrderClause(AphrontDatabaseConnection $conn_w, $phase) {
225277
switch ($phase) {
278+
case self::PHASE_LEASED:
279+
// Ideally we'd probably order these by lease acquisition time, but
280+
// we don't have that handy and this is a good approximation.
281+
return qsprintf($conn_w, 'ORDER BY priority ASC, id ASC');
226282
case self::PHASE_UNLEASED:
227283
// When selecting new tasks, we want to consume them in order of
228284
// increasing priority (and then FIFO).

src/infrastructure/daemon/workers/storage/PhabricatorWorkerActiveTask.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public function archiveTask($result, $duration) {
119119
->setFailureCount($this->getFailureCount())
120120
->setDataID($this->getDataID())
121121
->setPriority($this->getPriority())
122+
->setObjectPHID($this->getObjectPHID())
122123
->setResult($result)
123124
->setDuration($duration);
124125

src/infrastructure/daemon/workers/storage/PhabricatorWorkerArchiveTask.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public function unarchiveTask() {
8484
->setFailureCount(0)
8585
->setDataID($this->getDataID())
8686
->setPriority($this->getPriority())
87+
->setObjectPHID($this->getObjectPHID())
8788
->insert();
8889

8990
$this->setDataID(null);

0 commit comments

Comments
 (0)