/** * Look for a new job that can be processed with the current abilities and * from the specified group (or any if null). * * @param array $capabilities Available QueueWorkerTasks. * @param string|null $group Request a job from this group, (from any group if null) * @return \Queue\Model\Entity\QueuedJob|null */ public function requestJob(array $capabilities, $group = null) { $now = new Time(); $nowStr = $now->toDateTimeString(); $query = $this->find(); $options = ['conditions' => ['completed IS' => null, 'OR' => []], 'fields' => ['age' => $query->newExpr()->add('IFNULL(TIMESTAMPDIFF(SECOND, "' . $nowStr . '", notbefore), 0)')], 'order' => ['priority' => 'ASC', 'age' => 'ASC', 'id' => 'ASC']]; if ($group !== null) { $options['conditions']['job_group'] = $group; } // Generate the task specific conditions. foreach ($capabilities as $task) { list($plugin, $name) = pluginSplit($task['name']); $timeoutAt = $now->copy(); $tmp = ['job_type' => $name, 'AND' => [['OR' => ['notbefore <' => $now, 'notbefore IS' => null]], ['OR' => ['fetched <' => $timeoutAt->subSeconds($task['timeout']), 'fetched IS' => null]]], 'failed <' => $task['retries'] + 1]; if (array_key_exists('rate', $task) && $tmp['job_type'] && array_key_exists($tmp['job_type'], $this->rateHistory)) { $tmp['UNIX_TIMESTAMP() >='] = $this->rateHistory[$tmp['job_type']] + $task['rate']; } $options['conditions']['OR'][] = $tmp; } $job = $this->connection()->transactional(function () use($query, $options, $now) { $job = $query->find('all', $options)->autoFields(true)->first(); if (!$job) { return null; } $key = $this->key(); $job = $this->patchEntity($job, ['workerkey' => $key, 'fetched' => $now]); return $this->save($job); }); if (!$job) { return null; } $this->rateHistory[$job['job_type']] = $now->toUnixString(); return $job; }