Author: Chris Boulton (chris@bigcommerce.com)
示例#1
0
 public function registerEvents()
 {
     $job =& $this->job;
     Event::listen(Event::JOB_PERFORM, function ($event, $_job) use(&$job) {
         $job = $_job;
     });
 }
示例#2
0
 /**
  * Enqueue a job for execution at a given timestamp.
  *
  * Identical to Resque::enqueue, however the first argument is a timestamp
  * (either UNIX timestamp in integer format or an instance of the DateTime
  * class in PHP).
  *
  * @param DateTime|int $at    Instance of PHP DateTime object or int of UNIX timestamp.
  * @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.
  */
 public static function enqueueAt($at, $queue, $class, $args = array())
 {
     self::validateJob($class, $queue);
     $job = self::jobToHash($queue, $class, $args);
     self::delayedPush($at, $job);
     Event::trigger('afterSchedule', array('at' => $at, 'queue' => $queue, 'class' => $class, 'args' => $args));
 }
示例#3
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']);
     }
 }
示例#4
0
 /**
  * Mark the current job as having failed
  * 
  * @param \Exception $e
  */
 public function fail(\Exception $e)
 {
     $this->stopped();
     $this->setStatus(Job::STATUS_FAILED, $e);
     // For the failed jobs we store a lot more data for debugging
     $packet = $this->getPacket();
     $failed_payload = array_merge(json_decode($this->payload, true), array('worker' => $packet['worker'], 'started' => $packet['started'], 'finished' => $packet['finished'], 'output' => $packet['output'], 'exception' => (array) json_decode($packet['exception'], true)));
     $this->redis->zadd(Queue::redisKey($this->queue, 'failed'), time(), json_encode($failed_payload));
     Stats::incr('failed', 1);
     Stats::incr('failed', 1, Queue::redisKey($this->queue, 'stats'));
     Event::fire(Event::JOB_FAILURE, array($this, $e));
 }
示例#5
0
文件: Job.php 项目: shonm/php-resque
 /**
  * Mark the current job as having failed.
  *
  * @param $exception
  */
 public function fail($exception)
 {
     Event::trigger('onFailure', array('exception' => $exception, 'job' => $this));
     $this->updateStatus(Status::STATUS_FAILED);
     Failure::create($this->payload, $exception, $this->worker, $this->queue);
     Stat::incr('failed');
     Stat::incr('failed:' . $this->worker);
 }
示例#6
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;
 }
示例#7
0
 /**
  * Initialises the command just after the input has been validated.
  *
  * This is mainly useful when a lot of commands extends one main command
  * where some things need to be initialised based on the input arguments and options.
  *
  * @param InputInterface  $input  An InputInterface instance
  * @param OutputInterface $output An OutputInterface instance
  * @return void
  */
 protected function initialize(InputInterface $input, OutputInterface $output)
 {
     $this->parseConfig($input->getOptions(), $this->getNativeDefinition()->getOptionDefaults());
     $config = $this->getConfig();
     // Configure Redis
     Resque\Redis::setConfig(array('scheme' => $config['scheme'], 'host' => $config['host'], 'port' => $config['port'], 'namespace' => $config['namespace'], 'password' => $config['password']));
     // Set the verbosity
     if (array_key_exists('verbose', $config)) {
         if (!$input->getOption('verbose') and !$input->getOption('quiet') and is_int($config['verbose'])) {
             $output->setVerbosity($config['verbose']);
         } else {
             $this->config['verbose'] = $output->getVerbosity();
         }
     }
     // Set the monolog loggers, it's possible to speficfy multiple handlers
     $logs = array_key_exists('log', $config) ? array_unique($config['log']) : array();
     empty($logs) and $logs[] = 'console';
     $handlerConnector = new Resque\Logger\Handler\Connector($this, $input, $output);
     $handlers = array();
     foreach ($logs as $log) {
         $handlers[] = $handlerConnector->resolve($log);
     }
     $this->logger = $logger = new Resque\Logger($handlers);
     // Unset some variables so as not to pass to include file
     unset($logs, $handlerConnector, $handlers);
     // Include file?
     if (array_key_exists('include', $config) and strlen($include = $config['include'])) {
         if (!($includeFile = realpath(dirname($include) . '/' . basename($include))) or !is_readable($includeFile) or !is_file($includeFile) or substr($includeFile, -4) !== '.php') {
             throw new \InvalidArgumentException('The include file "' . $include . '" is not a readable php file.');
         }
         try {
             require_once $includeFile;
         } catch (\Exception $e) {
             throw new \RuntimeException('The include file "' . $include . '" threw an exception: "' . $e->getMessage() . '" on line ' . $e->getLine());
         }
     }
     // This outputs all the events that are fired, useful for learning
     // about when events are fired in the command flow
     if (array_key_exists('events', $config) and $config['events'] === true) {
         Resque\Event::listen('*', function ($event) use($output) {
             $data = array_map(function ($d) {
                 $d instanceof \Exception and $d = '"' . $d->getMessage() . '"';
                 is_array($d) and $d = '[' . implode(',', $d) . ']';
                 return (string) $d;
             }, array_slice(func_get_args(), 1));
             $output->writeln('<comment>-> event:' . Resque\Event::eventName($event) . '(' . implode(',', $data) . ')</comment>');
         });
     }
 }
示例#8
0
<?php

use Resque\Event;
use Resque\Logger;
// Test job class
class TestJob
{
    public function perform($args)
    {
        // Don't do anything
    }
}
// Lets record the forking time
Event::listen(array(Event::WORKER_FORK, Event::WORKER_FORK_CHILD), function ($event, $job) use($logger) {
    static $start = 0;
    if ($event === Event::WORKER_FORK_CHILD) {
        $exec = microtime(true) - $start;
        $logger->log('Forking process took ' . round($exec * 1000, 2) . 'ms', Logger::DEBUG);
    } else {
        $start = microtime(true);
    }
});
// When the job is about to be run, queue another one
Event::listen(Event::JOB_PERFORM, function ($event, $job) use($logger) {
    Resque::push('TestJob');
});
// Add a few jobs to the default queue
for ($i = 0; $i < 10; $i++) {
    Resque::push('TestJob');
}
示例#9
0
 /**
  * Perform necessary actions to start a worker.
  */
 private function startup()
 {
     $this->registerSigHandlers();
     $this->pruneDeadWorkers();
     Event::trigger('beforeFirstFork', $this);
     $this->registerWorker();
 }