/**
  * Run to start workers
  */
 public function run()
 {
     if (empty($this->queues)) {
         die('Set queues var containing the list of queues to work.' . PHP_EOL);
     }
     Resque::setBackend($this->redisBackend, $this->database, $this->password);
     if ($this->count > 1) {
         for ($i = 0; $i < $this->count; ++$i) {
             $pid = pcntl_fork();
             if ($pid == -1) {
                 die('Could not fork worker ' . $i . PHP_EOL);
             } elseif (!$pid) {
                 // Child, start the worker
                 $this->_startWorker();
                 break;
             }
         }
     } else {
         if (!empty($this->pidFile)) {
             file_put_contents($this->pidFile, getmypid()) or die('Could not write PID information to ' . $PIDFILE . PHP_EOL);
         }
         // Start a single worker
         $this->_startWorker();
     }
 }
Example #2
0
 /**
  * Push a new job onto the queue
  *
  * @param  string $job   The job class
  * @param  mixed  $data  The job data
  * @param  string $queue The queue to add the job to
  * @return Job job instance
  */
 public function push($job, array $data = null, $queue = null)
 {
     if (false !== ($delay = \Resque::getConfig('default.jobs.delay', false))) {
         return $this->later($delay, $job, $data, $queue);
     }
     return Job::create($this->getQueue($queue), $job, $data);
 }
 public function testAfterEnqueueEventCallbackFires()
 {
     $callback = 'afterEnqueueEventCallback';
     $event = 'afterEnqueue';
     Event::listen($event, array($this, $callback));
     Resque::enqueue('jobs', TestJob::className(), array('somevar'));
     $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called');
 }
Example #4
0
 /**
  * Find the next available job from the specified queue and return an
  * instance of Job for it.
  *
  * @param  string      $queue The name of the queue to check for a job in.
  * @return null|object Null when there aren't any waiting jobs, instance of Job when a job was found.
  */
 public static function reserve($queue = '*')
 {
     $payload = Resque::pop($queue);
     if (!is_array($payload)) {
         return false;
     }
     return new Job($queue, $payload);
 }
Example #5
0
 /**
  * Schedule all of the delayed jobs for a given timestamp.
  *
  * Searches for all items for a given timestamp, pulls them off the list of
  * delayed jobs and pushes them across to Resque.
  *
  * @param DateTime|int $timestamp Search for any items up to this timestamp to schedule.
  */
 public function enqueueDelayedItemsForTimestamp($timestamp)
 {
     $item = null;
     while ($item = Scheduler::nextItemForTimestamp($timestamp)) {
         $this->log('queueing ' . $item['class'] . ' in ' . $item['queue'] . ' [delayed]');
         if (!empty($item['args'])) {
             $item['args'] = reset($item['args']);
         }
         Event::trigger('beforeDelayedEnqueue', array('queue' => $item['queue'], 'class' => $item['class'], 'args' => $item['args']));
         Resque::enqueue($item['queue'], $item['class'], $item['args']);
     }
 }
Example #6
0
 /**
  * Initialize a failed job class and save it (where appropriate).
  *
  * @param object $payload   Object containing details of the failed job.
  * @param object $exception Instance of the exception that was thrown by the failed job.
  * @param object $worker    Instance of \Resque\Worker that received the job.
  * @param string $queue     The name of the queue the job was fetched from.
  */
 public function __construct($payload, $exception, $worker, $queue)
 {
     $data = new \stdClass();
     $data->failed_at = strftime('%a %b %d %H:%M:%S %Z %Y');
     $data->payload = $payload;
     $data->exception = get_class($exception);
     $data->error = $exception->getMessage();
     $data->backtrace = explode("\n", $exception->getTraceAsString());
     $data->worker = (string) $worker;
     $data->queue = $queue;
     $data = json_encode($data);
     Resque::redis()->rpush('failed', $data);
 }
 public function testRecreatedJobWithTrackingStillTracksStatus()
 {
     $originalToken = Resque::enqueue('jobs', TestJob::className(), 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());
 }
Example #8
0
 /**
  * Seperate the job from the worker via pcntl_fork
  *
  * @param Job $job
  */
 public function perform(Job $job)
 {
     $this->child = Resque::fork();
     // Forked and we're the child. Run the job.
     if ($this->child === 0) {
         parent::perform($job);
         exit(0);
     }
     // Parent process, sit and wait
     if ($this->child > 0) {
         $status = 'Forked ' . $this->child . ' at ' . strftime('%F %T');
         $this->worker->updateProcLine($status);
         $this->worker->log($status);
         // Wait until the child process finishes before continuing
         pcntl_wait($status);
         $exitStatus = pcntl_wexitstatus($status);
         if ($exitStatus !== 0) {
             $job->fail(new Job\DirtyExitException('Job exited with exit code ' . $exitStatus));
         }
     }
     $this->child = null;
 }
Example #9
0
 /**
  * Return an object describing the job this worker is currently working on.
  *
  * @return object Object with details of current job.
  */
 public function job()
 {
     $job = Resque::redis()->get('worker:' . $this);
     if (!$job) {
         return array();
     } else {
         return json_decode($job, true);
     }
 }
Example #10
0
 public function testJobWithNamespace()
 {
     Redis::prefix('php');
     $queue = 'jobs';
     $payload = array('another_value');
     Resque::enqueue($queue, JobWithTearDown::className(), $payload);
     $this->assertEquals(Resque::queues(), array('jobs'));
     $this->assertEquals(Resque::size($queue), 1);
     Redis::prefix('resque');
     $this->assertEquals(Resque::size($queue), 0);
 }
Example #11
0
 /**
  * Pop a job off the delayed queue for a given timestamp.
  *
  * @param DateTime|int $timestamp Instance of DateTime or UNIX timestamp.
  *
  * @return array Matching job at timestamp.
  */
 public static function nextItemForTimestamp($timestamp)
 {
     $timestamp = self::getTimestamp($timestamp);
     $key = 'delayed:' . $timestamp;
     $item = json_decode(Resque::redis()->lpop($key), true);
     self::cleanupTimestamp($key, $timestamp);
     return $item;
 }
Example #12
0
<?php

require_once __DIR__ . '/../autoload.php';
use resque\Resque;
if (empty($argv[1])) {
    die('Specify the name of a job to add. e.g, php queue.php PHP_Job');
}
date_default_timezone_set('GMT');
// Resque::setBackend('127.0.0.1:6379', 0, 'your password');
Resque::setBackend('127.0.0.1:6379');
$args = array('time' => time(), 'array' => array('test' => 'test'));
$jobId = Resque::enqueue('default', $argv[1], $args, true);
echo "Queued job " . $jobId . "\n\n";
Example #13
0
 /**
  * Look for any jobs which are running but the worker is dead.
  * Meaning that they are also not running but left in limbo
  *
  * This is a form of garbage collection to handle cases where the
  * server may have been killed and the workers did not die gracefully
  * and therefore leave state information in Redis.
  *
  * @param array $queues list of queues to check
  */
 public static function cleanup(array $queues = array('*'))
 {
     $cleaned = array('zombie' => 0, 'processed' => 0);
     $redis = Redis::instance();
     if (in_array('*', $queues)) {
         $queues = (array) $redis->smembers(Queue::redisKey());
         sort($queues);
     }
     $workers = $redis->smembers(Worker::redisKey());
     foreach ($queues as $queue) {
         $jobs = $redis->zrangebyscore(Queue::redisKey($queue, 'running'), 0, time());
         foreach ($jobs as $payload) {
             $job = self::loadPayload($queue, $payload);
             $packet = $job->getPacket();
             if (!in_array($packet['worker'], $workers)) {
                 $job->fail(new Exception\Zombie());
                 $cleaned['zombie']++;
             }
         }
         $cleaned['processed'] = $redis->zremrangebyscore(Queue::redisKey($queue, 'processed'), 0, time() - \Resque::getConfig('default.expiry_time', \Resque::DEFAULT_EXPIRY_TIME));
     }
     return $cleaned;
 }
Example #14
0
 /**
  * Find the next available job from the specified queues using blocking list pop
  * and return an instance of Job for it.
  *
  * @param array             $queues
  * @param int               $timeout
  * @return null|object Null when there aren't any waiting jobs, instance of Job when a job was found.
  */
 public static function reserveBlocking(array $queues, $timeout = null)
 {
     $item = Resque::blpop($queues, $timeout);
     if (!is_array($item)) {
         return false;
     }
     return new Job($item['queue'], $item['payload']);
 }
Example #15
0
 /**
  * Return Redis
  *
  * @return object Redis instance
  */
 public function redis()
 {
     return Resque::redis();
 }
 public function testWorkerErasesItsStatsWhenShutdown()
 {
     Resque::enqueue('jobs', TestJob::className());
     Resque::enqueue('jobs', '\\resque\\test\\job\\InvalidJob');
     $worker = new Worker('jobs');
     $worker->work(0);
     $worker->work(0);
     $this->assertEquals(0, $worker->getStat('processed'));
     $this->assertEquals(0, $worker->getStat('failed'));
 }
<?php

require_once __DIR__ . '/../autoload.php';
use resque\Resque;
use resque\core\job\Status;
if (empty($argv[1])) {
    die('Specify the ID of a job to monitor the status of.');
}
date_default_timezone_set('GMT');
Resque::setBackend('127.0.0.1:6379');
$status = new Status($argv[1]);
if (!$status->isTracking()) {
    die("Resque is not tracking the status of this job.\n");
}
echo "Tracking status of " . $argv[1] . ". Press [break] to stop.\n\n";
while (true) {
    fwrite(STDOUT, "Status of " . $argv[1] . " is: " . $status->get() . "\n");
    sleep(1);
}
Example #18
0
 /**
  * Delete a statistic with the given name.
  *
  * @param string $stat The name of the statistic to delete.
  * @return boolean True if successful, false if not.
  */
 public static function clear($stat)
 {
     return (bool) Resque::redis()->del('stat:' . $stat);
 }
Example #19
0
 /**
  * Look for any workers which should be running on this server and if
  * they're not, remove them from Redis.
  *
  * This is a form of garbage collection to handle cases where the
  * server may have been killed and the workers did not die gracefully
  * and therefore leave state information in Redis.
  */
 public function cleanup()
 {
     $workers = self::allWorkers();
     $hosts = $this->redis->smembers(Host::redisKey());
     $cleaned = array();
     foreach ($workers as $worker) {
         list($host, $pid) = explode(':', (string) $worker, 2);
         if ($host != (string) $this->host and in_array($host, $hosts) or $host == (string) $this->host and posix_kill((int) $pid, 0)) {
             continue;
         }
         $this->log('Pruning dead worker: ' . $worker, Logger::DEBUG);
         $worker->unregister();
         $cleaned[] = (string) $worker;
     }
     $workerIds = array_map(function ($w) {
         return (string) $w;
     }, $workers);
     $keys = (array) $this->redis->keys('worker:' . $this->host . ':*');
     foreach ($keys as $key) {
         $key = $this->redis->removeNamespace($key);
         $id = substr($key, strlen('worker:'));
         if (!in_array($id, $workerIds)) {
             if ($this->redis->ttl($key) < 0) {
                 $this->log('Expiring worker data: ' . $key, Logger::DEBUG);
                 $this->redis->expire($key, \Resque::getConfig('default.expiry_time', \Resque::DEFAULT_EXPIRY_TIME));
             }
         }
     }
     Event::fire(Event::WORKER_CLEANUP, array($this, $cleaned));
     return $cleaned;
 }
Example #20
0
 /**
  * Stop tracking the status of a job.
  */
 public function stop()
 {
     Resque::redis()->del((string) $this);
 }
Example #21
0
 /**
  * 异常日志入队列
  *
  * @access public
  * @return void
  */
 public function errorLog()
 {
     if (isset(Application::app()->getConfig()->application->queue) && isset(Application::app()->getConfig()->application->queue->redis) && isset(Application::app()->getConfig()->application->queue->log)) {
         $queue = Application::app()->getConfig()->application->queue->toArray();
         $redis_config = $queue['redis'];
         $server = $redis_config['host'] . ':' . $redis_config['port'];
         $database = isset($redis_config['database']) ? $redis_config['database'] : null;
         Resque::setBackend($server, $database);
         $args = array('module' => $queue['log']['module'], 'controller' => $queue['log']['controller'], 'action' => $queue['log']['action'], 'args' => $this->toArray());
         $queue_name = Application::app()->getConfig()->application->queue->log->name;
         Resque::enqueue($queue_name, 'Resque\\Job\\YafCLIRequest', $args, true);
     }
 }
Example #22
0
 /**
  * Create a new job and save it to the specified queue.
  *
  * @param string $queue The name of the queue to place the job in.
  * @param string $class The name of the class that contains the code to execute the job.
  * @param array $args Any optional arguments that should be passed when the job is executed.
  * @param boolean $trackStatus Set to true to be able to monitor the status of a job.
  *
  * @return string|boolean Job ID when the job was created, false if creation was cancelled due to beforeEnqueue
  */
 public static function enqueue($queue, $class, $args = null, $trackStatus = false)
 {
     $id = Resque::generateJobId();
     $hookParams = ['class' => $class, 'args' => $args, 'queue' => $queue, 'id' => $id];
     try {
         Event::trigger('beforeEnqueue', $hookParams);
     } catch (Job\DontCreate $e) {
         return false;
     }
     Job::create($queue, $class, $args, $trackStatus, $id);
     Event::trigger('afterEnqueue', $hookParams);
     return $id;
 }
    echo "Cannot find redis-server in path. Please make sure redis is installed.\n";
    exit(1);
}
exec('cd ' . TEST_MISC . '; redis-server ' . REDIS_CONF, $output, $returnVar);
usleep(500000);
if ($returnVar != 0) {
    echo "Cannot start redis-server.\n";
    exit(1);
}
// Get redis port from conf
$config = file_get_contents(REDIS_CONF);
if (!preg_match('#^\\s*port\\s+([0-9]+)#m', $config, $matches)) {
    echo "Could not determine redis port from redis.conf";
    exit(1);
}
Resque::setBackend('localhost:' . $matches[1]);
// Shutdown
function killRedis($pid)
{
    if (getmypid() !== $pid) {
        return;
        // don't kill from a forked worker
    }
    $config = file_get_contents(REDIS_CONF);
    if (!preg_match('#^\\s*pidfile\\s+([^\\s]+)#m', $config, $matches)) {
        return;
    }
    $pidFile = TEST_MISC . '/' . $matches[1];
    if (file_exists($pidFile)) {
        $pid = trim(file_get_contents($pidFile));
        posix_kill((int) $pid, 9);