Skip to content

Commit 0ed281d

Browse files
author
epriestley
committedDec 9, 2013
Make taskmaster consumption of failed tasks more FIFO-ey
Summary: Ref T1049. See discussion in D7745. We have some specific interest in this for D7745, but generally we want to consume tasks with expired leases in roughly FIFO order, just like we consume new tasks in roughly FIFO order. Currently, when we select an expired task we order them by `id`, but this is the original insert order, not lease expiration order. Instead, order by `leaseExpires`. This query is actually much better than the old one was, since the WHERE part is `leaseExpries < VALUE`. Test Plan: Ran `EXPLAIN` on the query. Ran a taskmaster in debug mode and saw it lease new and expired tasks successfully. Reviewers: hach-que, btrahan Reviewed By: hach-que CC: aran Maniphest Tasks: T1049 Differential Revision: https://secure.phabricator.com/D7746
1 parent 8fd256a commit 0ed281d

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed
 

‎src/infrastructure/daemon/workers/__tests__/PhabricatorWorkerTestCase.php

+18-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ public function testNewBeforeLeased() {
4949
$this->expectNextLease($task1);
5050
}
5151

52-
5352
public function testExecuteTask() {
5453
$task = $this->scheduleAndExecuteTask();
5554

@@ -155,6 +154,24 @@ public function testRequiredLeaseTime() {
155154
$this->assertEqual(true, ($task->getLeaseExpires() - time()) > 1000);
156155
}
157156

157+
public function testLeasedIsOldestFirst() {
158+
// Tasks which expired earlier should lease first, all else being equal.
159+
160+
$task1 = $this->scheduleTask();
161+
$task2 = $this->scheduleTask();
162+
163+
$task1->setLeaseOwner('test');
164+
$task1->setLeaseExpires(time() - 100000);
165+
$task1->forceSaveWithoutLease();
166+
167+
$task2->setLeaseOwner('test');
168+
$task2->setLeaseExpires(time() - 200000);
169+
$task2->forceSaveWithoutLease();
170+
171+
$this->expectNextLease($task2);
172+
$this->expectNextLease($task1);
173+
}
174+
158175
private function expectNextLease($task) {
159176
$leased = id(new PhabricatorWorkerLeaseQuery())
160177
->setLimit(1)

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

+22-4
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public function execute() {
6060
'SELECT id, leaseOwner FROM %T %Q %Q %Q',
6161
$task_table->getTableName(),
6262
$this->buildWhereClause($conn_w, $phase),
63-
$this->buildOrderClause($conn_w),
63+
$this->buildOrderClause($conn_w, $phase),
6464
$this->buildLimitClause($conn_w, $limit - $leased));
6565

6666
// NOTE: Sometimes, we'll race with another worker and they'll grab
@@ -102,7 +102,7 @@ public function execute() {
102102
$task_table->getTableName(),
103103
$taskdata_table->getTableName(),
104104
$lease_ownership_name,
105-
$this->buildOrderClause($conn_w),
105+
$this->buildOrderClause($conn_w, $phase),
106106
$this->buildLimitClause($conn_w, $limit));
107107

108108
$tasks = $task_table->loadAllFromArray($data);
@@ -188,8 +188,26 @@ private function buildUpdateWhereClause(
188188

189189
}
190190

191-
private function buildOrderClause(AphrontDatabaseConnection $conn_w) {
192-
return qsprintf($conn_w, 'ORDER BY id ASC');
191+
private function buildOrderClause(AphrontDatabaseConnection $conn_w, $phase) {
192+
switch ($phase) {
193+
case self::PHASE_UNLEASED:
194+
// When selecting new tasks, we want to consume them in roughly
195+
// FIFO order, so we order by the task ID.
196+
return qsprintf($conn_w, 'ORDER BY id ASC');
197+
case self::PHASE_EXPIRED:
198+
// When selecting failed tasks, we want to consume them in roughly
199+
// FIFO order of their failures, which is not necessarily their original
200+
// queue order.
201+
202+
// Particularly, this is important for tasks which use soft failures to
203+
// indicate that they are waiting on other tasks to complete: we need to
204+
// push them to the end of the queue after they fail, at least on
205+
// average, so we don't deadlock retrying the same blocked task over
206+
// and over again.
207+
return qsprintf($conn_w, 'ORDER BY leaseExpires ASC');
208+
default:
209+
throw new Exception(pht('Unknown phase "%s"!', $phase));
210+
}
193211
}
194212

195213
private function buildLimitClause(AphrontDatabaseConnection $conn_w, $limit) {

0 commit comments

Comments
 (0)
Failed to load comments.