public function execute()
 {
     $task_table = new PhabricatorWorkerActiveTask();
     $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);
 }
 public function execute()
 {
     if (!$this->limit) {
         throw new Exception('You must setLimit() when leasing tasks.');
     }
     $task_table = new PhabricatorWorkerActiveTask();
     $taskdata_table = new PhabricatorWorkerTaskData();
     $lease_ownership_name = $this->getLeaseOwnershipName();
     $conn_w = $task_table->establishConnection('w');
     // Try to satisfy the request from new, unleased tasks first. If we don't
     // find enough tasks, try tasks with expired leases (i.e., tasks which have
     // previously failed).
     $phases = array(self::PHASE_UNLEASED, self::PHASE_EXPIRED);
     $limit = $this->limit;
     $leased = 0;
     foreach ($phases as $phase) {
         // NOTE: If we issue `UPDATE ... WHERE ... ORDER BY id ASC`, the query
         // goes very, very slowly. The `ORDER BY` triggers this, although we get
         // the same apparent results without it. Without the ORDER BY, binary
         // read slaves complain that the query isn't repeatable. To avoid both
         // problems, do a SELECT and then an UPDATE.
         $rows = queryfx_all($conn_w, 'SELECT id, leaseOwner FROM %T %Q %Q %Q', $task_table->getTableName(), $this->buildWhereClause($conn_w, $phase), $this->buildOrderClause($conn_w, $phase), $this->buildLimitClause($conn_w, $limit - $leased));
         // NOTE: Sometimes, we'll race with another worker and they'll grab
         // this task before we do. We could reduce how often this happens by
         // selecting more tasks than we need, then shuffling them and trying
         // to lock only the number we're actually after. However, the amount
         // of time workers spend here should be very small relative to their
         // total runtime, so keep it simple for the moment.
         if ($rows) {
             queryfx($conn_w, 'UPDATE %T task
         SET leaseOwner = %s, leaseExpires = UNIX_TIMESTAMP() + %d
         %Q', $task_table->getTableName(), $lease_ownership_name, self::getDefaultLeaseDuration(), $this->buildUpdateWhereClause($conn_w, $phase, $rows));
             $leased += $conn_w->getAffectedRows();
             if ($leased == $limit) {
                 break;
             }
         }
     }
     if (!$leased) {
         return array();
     }
     $data = queryfx_all($conn_w, 'SELECT task.*, taskdata.data _taskData, UNIX_TIMESTAMP() _serverTime
     FROM %T task LEFT JOIN %T taskdata
       ON taskdata.id = task.dataID
     WHERE leaseOwner = %s AND leaseExpires > UNIX_TIMESTAMP()
     %Q %Q', $task_table->getTableName(), $taskdata_table->getTableName(), $lease_ownership_name, $this->buildOrderClause($conn_w, $phase), $this->buildLimitClause($conn_w, $limit));
     $tasks = $task_table->loadAllFromArray($data);
     $tasks = mpull($tasks, null, 'getID');
     foreach ($data as $row) {
         $tasks[$row['id']]->setServerTime($row['_serverTime']);
         if ($row['_taskData']) {
             $task_data = json_decode($row['_taskData'], true);
         } else {
             $task_data = null;
         }
         $tasks[$row['id']]->setData($task_data);
     }
     return $tasks;
 }