protected function execute(InputInterface $input, OutputInterface $output) { $host = new Resque\Host(); $cleaned_hosts = $host->cleanup(); $worker = new Resque\Worker('*'); $cleaned_workers = $worker->cleanup(); $cleaned_hosts = array_merge_recursive($cleaned_hosts, $host->cleanup()); $cleaned_jobs = Resque\Job::cleanup(); $this->log('Cleaned hosts: <pop>' . json_encode($cleaned_hosts['hosts']) . '</pop>'); $this->log('Cleaned workers: <pop>' . json_encode(array_merge($cleaned_hosts['workers'], $cleaned_workers)) . '</pop>'); $this->log('Cleaned <pop>' . $cleaned_jobs['zombie'] . '</pop> zombie job' . ($cleaned_jobs['zombie'] == 1 ? '' : 's')); $this->log('Cleared <pop>' . $cleaned_jobs['processed'] . '</pop> processed job' . ($cleaned_jobs['processed'] == 1 ? '' : 's')); }
public function getJobStatus($jobId) { $job = Job::load($jobId); return $job->getStatus(); }
/** * Find any delayed jobs and add them to the queue if found * * @param int $endTime optional end time for range * @param int $startTime optional start time for range */ public function queueDelayed($endTime = null, $startTime = 0) { $startTime = $startTime ?: 0; $endTime = $endTime ?: time(); foreach ($this->resolveQueues() as $queue) { $this->redis->multi(); $jobs = $this->redis->zrangebyscore(Queue::redisKey($queue, 'delayed'), $startTime, $endTime); $this->redis->zremrangebyscore(Queue::redisKey($queue, 'delayed'), $startTime, $endTime); list($jobs, $found) = $this->redis->exec(); if ($found > 0) { foreach ($jobs as $payload) { $job = Job::loadPayload($queue, $payload); $job->setWorker($this); if (Event::fire(Event::JOB_QUEUE_DELAYED, $job) !== false) { $job->queue(); Event::fire(Event::JOB_QUEUED_DELAYED, $job); } } Stats::decr('delayed', $found); Stats::decr('delayed', $found, Queue::redisKey($queue, 'stats')); $this->log('Added <pop>' . $found . '</pop> delayed job' . ($found == 1 ? '' : 's') . ' to <pop>' . $queue . '</pop> queue', Logger::NOTICE); } } }
/** * Tell Redis which job we're currently working on. * * @param Job $job Job instance containing the job we're working on. */ public function workingOn(Job $job) { $job->worker = $this; $this->currentJob = $job; $job->updateStatus(Job\Status::STATUS_RUNNING); $data = json_encode(array('queue' => $job->queue, 'run_at' => strftime('%a %b %d %H:%M:%S %Z %Y'), 'payload' => $job->payload)); Resque::redis()->set('worker:' . $job->worker, $data); }
protected function execute(InputInterface $input, OutputInterface $output) { $host = $this->getConfig('listenhost'); $port = $this->getConfig('listenport'); $retry = $this->getConfig('listenretry'); $timeout = $this->getConfig('listentimeout'); $server = new Socket\Server(array('ip' => $host, 'port' => $port), $this->logger); do { try { $server->start(); } catch (Socket\Exception $e) { if ($retry) { $server->log('<error>Socket server failure: "' . $e->getMessage() . '". Retrying in ' . $timeout . ' seconds...</error>'); sleep($timeout); continue; } throw $e; } break; } while ($retry); $command = $this; $server->onConnect(function ($server, &$client, $input) { // }); $server->onDisconnect(function ($server, &$client, $message) { $server->send($client, $message); }); $server->onReceive(function ($server, &$client, $input) use($command) { if (!($data = json_decode(trim($input), true))) { $data = trim($input); } if (is_array($data)) { $cmd = $data['cmd']; unset($data['cmd']); } else { try { $input = new StringInput($data, new InputDefinition(array(new InputArgument('cmd', InputArgument::REQUIRED), new InputArgument('id', InputArgument::OPTIONAL), new InputOption('force', 'f', InputOption::VALUE_NONE), new InputOption('json', 'j', InputOption::VALUE_NONE)))); $cmd = $input->getArgument('cmd'); $data = array('id' => $input->getArgument('id'), 'force' => $input->getOption('force'), 'json' => $input->getOption('json')); } catch (\Exception $e) { $server->send($client, 'Command error: ' . $e->getMessage()); return; } } switch (strtolower($cmd)) { case 'shell': $server->send($client, 'Connected to php-resque on ' . $server . '. To quit, type "quit"'); break; case 'workers': $workers = Worker::hostWorkers(); if (empty($workers)) { $response = array('ok' => 0, 'message' => 'There are no workers running on this host.'); $server->send($client, $data['json'] ? json_encode($response) : $response['message']); return; } if ($data['json']) { $response = array('ok' => 1, 'data' => array()); foreach ($workers as $i => $worker) { $response['data'][] = $worker->getPacket(); } $server->send($client, json_encode($response)); } else { $table = new Resque\Helpers\Table($command); $table->setHeaders(array('#', 'Status', 'ID', 'Running for', 'Running job', 'P', 'C', 'F', 'Interval', 'Timeout', 'Memory (Limit)')); foreach ($workers as $i => $worker) { $packet = $worker->getPacket(); $table->addRow(array($i + 1, Worker::$statusText[$packet['status']], (string) $worker, Util::human_time_diff($packet['started']), !empty($packet['job_id']) ? $packet['job_id'] . ' for ' . Util::human_time_diff($packet['job_started']) : '-', $packet['processed'], $packet['cancelled'], $packet['failed'], $packet['interval'], $packet['timeout'], Util::bytes($packet['memory']) . ' (' . $packet['memory_limit'] . ' MB)')); } $server->send($client, (string) $table); } break; case 'worker:start': case 'worker:restart': $response = array('ok' => 0, 'message' => 'This command is not yet supported remotely.'); $server->send($client, $data['json'] ? json_encode($response) : $response['message']); break; case 'worker:pause': case 'worker:resume': case 'worker:stop': case 'worker:cancel': $valid_id = false; $id = preg_replace('/[^a-z0-9\\*:,\\.;-]/i', '', $data['id']); if (!empty($id)) { if (false === ($worker = Resque\Worker::hostWorker($id))) { if ($data['json']) { $response = array('ok' => 0, 'message' => 'Invalid worker id.'); $server->send($client, json_encode($response)); } else { $server->send($client, "Usage:\n\t{$cmd} <worker_id>\n\n" . "Help: You must specify a valid worker id, to get a \n" . "list of workers use the \"workers\" command."); } return; } $workers = array($worker); } else { $workers = Resque\Worker::hostWorkers(); if (empty($workers)) { $response = array('ok' => 0, 'message' => 'There are no workers on this host.'); $server->send($client, $data['json'] ? json_encode($response) : $response['message']); return; } } $cmd = $data['force'] ? 'worker:term' : $cmd; $signals = array('worker:pause' => SIGUSR2, 'worker:resume' => SIGCONT, 'worker:stop' => SIGQUIT, 'worker:term' => SIGTERM, 'worker:cancel' => SIGUSR1); $messages = array('worker:pause' => 'Paused worker %s', 'worker:resume' => 'Resumed worker %s', 'worker:stop' => 'Stopped worker %s', 'worker:term' => 'Force stopped worker %s', 'worker:cancel' => 'Cancelled running job on worker %s'); $response = array('ok' => 1, 'data' => array()); foreach ($workers as $worker) { $pid = $worker->getPid(); if ($cmd == 'worker:cancel') { $packet = $worker->getPacket(); $job_pid = (int) $packet['job_pid']; if ($job_pid and posix_kill($job_pid, 0)) { $pid = $job_pid; } else { $response['data'][] = array('ok' => 0, 'message' => 'The worker ' . $worker . ' has no running job to cancel.'); continue; } } if (posix_kill($pid, $signals[$cmd])) { $response['data'][] = array('ok' => 1, 'message' => sprintf($messages[$cmd], $worker)); } else { $response['data'][] = array('ok' => 0, 'message' => 'There was an error sending the signal, please try again.'); } } $server->send($client, $data['json'] ? json_encode($response) : implode(PHP_EOL, array_map(function ($d) { return $d['message']; }, $response['data']))); break; case 'job:queue': $response = array('ok' => 0, 'message' => 'Cannot queue remotely as it makes no sense. Use command `resque job:queue <job> <args> [--queue=<queue> [--delay=<delay>]]` locally.'); $server->send($client, $data['json'] ? json_encode($response) : $response['message']); break; case 'cleanup': $host = new Host(); $cleaned_hosts = $host->cleanup(); $worker = new Worker('*'); $cleaned_workers = $worker->cleanup(); $cleaned_hosts = array_merge_recursive($cleaned_hosts, $host->cleanup()); $cleaned_jobs = Job::cleanup(); if ($data['json']) { $response = array('ok' => 1, 'data' => array_merge($cleaned_hosts, $cleaned_workers, $cleaned_jobs)); $server->send($client, json_encode($response)); } else { $output = 'Cleaned hosts: ' . json_encode($cleaned_hosts['hosts']) . PHP_EOL . 'Cleaned workers: ' . json_encode(array_merge($cleaned_hosts['workers'], $cleaned_workers)) . PHP_EOL . 'Cleaned ' . $cleaned_jobs['zombie'] . ' zombie job' . ($cleaned_jobs['zombie'] == 1 ? '' : 's') . PHP_EOL . 'Cleared ' . $cleaned_jobs['processed'] . ' processed job' . ($cleaned_jobs['processed'] == 1 ? '' : 's'); } $server->send($client, $output); break; case 'shutdown': $server->shutdown(); break; case 'quit': case 'exit': $server->disconnect($client); break; default: $response = array('ok' => 0, 'message' => 'Sorry, I don\'t know what to do with command "' . $cmd . '".'); $server->send($client, $data['json'] ? json_encode($response) : $response['message']); break; } }); $server->run(); }
public function testRecreatedJobWithTrackingStillTracksStatus() { $originalToken = Resque::enqueue('jobs', '\\Test_Job', null, true); $job = $this->worker->reserve(); // Mark this job as being worked on to ensure that the new status is still // waiting. $this->worker->workingOn($job); // Now recreate it $newToken = $job->recreate(); // Make sure we've got a new job returned $this->assertNotEquals($originalToken, $newToken); // Now check the status of the new job $newJob = Job::reserve('jobs'); $this->assertEquals(Status::STATUS_WAITING, $newJob->getStatus()); }
/** * Pop the next job off of the queue. * * @param array $queues Queues to watch for new jobs * @param int $timeout Timeout if blocking * @param bool $blocking Should Redis use blocking * @return Job|false */ public function pop(array $queues, $timeout = 10, $blocking = true) { $queue = $payload = null; foreach ($queues as &$queue) { $queue = self::redisKey($queue); } if ($blocking) { list($queue, $payload) = $this->redis->blpop($queues, $timeout); $queue = $this->redis->removeNamespace($queue); } else { foreach ($queues as $queue) { if ($payload = $this->redis->lpop($queue)) { break; } } } if (!$queue or !$payload) { return false; } $queue = substr($queue, strlen('queue:')); return Job::loadPayload($queue, $payload); }