protected function execute(InputInterface $input, OutputInterface $output) { $dialog = $this->getHelperSet()->get('dialog'); if ($input->getOption('force') || $dialog->askConfirmation($output, 'Continuing will clear all php-resque data from Redis. Are you sure? ', false)) { $output->write('Clearing Redis php-resque data... '); $redis = Resque\Redis::instance(); $keys = $redis->keys('*'); foreach ($keys as $key) { $redis->del($key); } $output->writeln('<pop>Done.</pop>'); } }
/** * 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>'); }); } }
protected function execute(InputInterface $input, OutputInterface $output) { $queues = Resque\Redis::instance()->smembers('queues'); if (empty($queues)) { $this->log('<warn>There are no queues.</warn>'); return; } $table = new Resque\Helpers\Table($this); $table->setHeaders(array('#', 'Name', 'Queued', 'Delayed', 'Processed', 'Failed', 'Cancelled', 'Total')); foreach ($queues as $i => $queue) { $stats = Resque\Redis::instance()->hgetall(Resque\Queue::redisKey($queue, 'stats')); $table->addRow(array($i + 1, $queue, (int) @$stats['queued'], (int) @$stats['delayed'], (int) @$stats['processed'], (int) @$stats['failed'], (int) @$stats['cancelled'], (int) @$stats['total'])); } $this->log((string) $table); }
protected function execute(InputInterface $input, OutputInterface $output) { $hosts = Resque\Redis::instance()->smembers(Resque\Host::redisKey()); if (empty($hosts)) { $this->log('<warn>There are no hosts with running workers.</warn>'); return; } $table = new Resque\Helpers\Table($this); $table->setHeaders(array('#', 'Hostname', '# workers')); foreach ($hosts as $i => $hostname) { $host = new Resque\Host($hostname); $workers = Resque\Redis::instance()->scard(Resque\Host::redisKey($host)); $table->addRow(array($i + 1, $hostname, $workers)); } $this->log((string) $table); }
protected function execute(InputInterface $input, OutputInterface $output) { Resque\Redis::setConfig(array('namespace' => 'resque:speedtest')); $testTime = (int) $input->getOption('time') ?: 5; @unlink(RESQUE_DIR . '/test/speed/output.log'); $process = new Process(RESQUE_BIN_DIR . '/resque worker:start -c ' . RESQUE_DIR . '/test/speed/config.yml'); $start = microtime(true); $process->start(); do { $this->setProgress($output, Resque::stats(), $testTime, $start); usleep(500); } while ($process->isRunning() and $testTime > microtime(true) - $start); $process->stop(0, SIGTERM); if (!$process->isSuccessful()) { list($error) = explode('Exception trace:', $process->getErrorOutput()); $output->write('<error>' . $error . '</error>'); } // Clear down Redis $redis = Resque\Redis::instance(); $keys = $redis->keys('*'); foreach ($keys as $key) { $redis->del($key); } }
/** * 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; }
/** * Gets Resque stats * * @return array */ public static function stats() { return Redis::instance()->hgetall('stats'); }
/** * Delete a statistic with the given name. * * @param string $stat The name of the statistic to delete. * @param string $key The stat key to use * @return boolean True if successful, false if not. */ public static function clear($stat, $key = Stats::DEFAULT_KEY) { return (bool) Redis::instance()->hdel($key, $stat); }
/** * Return all known workers * * @param string $host Hostname * @param Logger $logger Logger * @return array */ public static function hostWorkers($host = null, Logger $logger = null) { if (!($ids = Redis::instance()->smembers(self::redisKey()))) { return array(); } $host = $host ?: (function_exists('gethostname') ? gethostname() : php_uname('n')); $workers = array(); foreach ($ids as $id) { if (strpos($id, $host . ':') !== false and ($worker = self::fromId($id, $logger)) !== false) { $workers[] = $worker; } } return $workers; }
/** * Create a new host */ public function __construct($hostname = null) { $this->redis = Redis::instance(); $this->hostname = $hostname ?: (function_exists('gethostname') ? gethostname() : php_uname('n')); }
/** * Create a new queue instance * * @param string $default Name of default queue to add job to */ public function __construct($default = null) { $this->redis = Redis::instance(); $this->default = $default ?: \Resque::getConfig('default.jobs.queue', 'default'); }