diff --git a/.gitignore b/.gitignore
index a793d958..0e094d22 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
vendor/
*.swp
phpunit.xml
+.idea
diff --git a/bin/resque b/bin/resque
index 1d604851..aa94cb47 100755
--- a/bin/resque
+++ b/bin/resque
@@ -2,12 +2,12 @@
1) {
+if (!empty($COUNT) && $COUNT > 1) {
$count = $COUNT;
}
$PREFIX = getenv('PREFIX');
-if(!empty($PREFIX)) {
- $logger->log(Psr\Log\LogLevel::INFO, 'Prefix set to {prefix}', array('prefix' => $PREFIX));
+if (!empty($PREFIX)) {
+ $logger->log(Psr\Log\LogLevel::INFO, 'Prefix set to {prefix}', ['prefix' => $PREFIX]);
Resque_Redis::prefix($PREFIX);
}
-if($count > 1) {
- for($i = 0; $i < $count; ++$i) {
+if ($count > 1) {
+ for ($i = 0; $i < $count; ++$i) {
$pid = Resque::fork();
- if($pid === false || $pid === -1) {
- $logger->log(Psr\Log\LogLevel::EMERGENCY, 'Could not fork worker {count}', array('count' => $i));
+ if ($pid === false || $pid === -1) {
+ $logger->log(Psr\Log\LogLevel::EMERGENCY, 'Could not fork worker {count}', ['count' => $i]);
die();
- }
- // Child, start the worker
- else if(!$pid) {
+ } elseif (!$pid) {
+ // Child, start the worker
$queues = explode(',', $QUEUE);
$worker = new Resque_Worker($queues);
$worker->setLogger($logger);
- $logger->log(Psr\Log\LogLevel::NOTICE, 'Starting worker {worker}', array('worker' => $worker));
+ $logger->log(Psr\Log\LogLevel::NOTICE, 'Starting worker {worker}', ['worker' => $worker]);
$worker->work($interval, $BLOCKING);
break;
}
}
-}
-// Start a single worker
+} // Start a single worker
else {
$queues = explode(',', $QUEUE);
$worker = new Resque_Worker($queues);
@@ -120,10 +120,10 @@ else {
$PIDFILE = getenv('PIDFILE');
if ($PIDFILE) {
file_put_contents($PIDFILE, getmypid()) or
- die('Could not write PID information to ' . $PIDFILE);
+ die('Could not write PID information to ' . $PIDFILE);
}
- $logger->log(Psr\Log\LogLevel::NOTICE, 'Starting worker {worker}', array('worker' => $worker));
+ $logger->log(Psr\Log\LogLevel::NOTICE, 'Starting worker {worker}', ['worker' => $worker]);
$worker->work($interval, $BLOCKING);
}
?>
diff --git a/build.xml b/build.xml
index 7289999c..bb1a1b53 100644
--- a/build.xml
+++ b/build.xml
@@ -1,17 +1,17 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+ --coverage-html ${basedir}/build/coverage"/>
+
+
+
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 28a0bf58..ab6dcb91 100644
--- a/composer.json
+++ b/composer.json
@@ -1,41 +1,50 @@
{
- "name": "chrisboulton/php-resque",
- "type": "library",
- "description": "Redis backed library for creating background jobs and processing them later. Based on resque for Ruby.",
- "keywords": ["job", "background", "redis", "resque"],
- "homepage": "http://www.github.com/chrisboulton/php-resque/",
- "license": "MIT",
- "authors": [
- {
- "name": "Chris Boulton",
- "email": "chris@bigcommerce.com"
- }
- ],
- "repositories": [
- {
- "type": "vcs",
- "url": "https://github.com/chrisboulton/credis"
- }
- ],
- "require": {
- "php": ">=5.3.0",
- "ext-pcntl": "*",
- "colinmollenhour/credis": "~1.7",
- "psr/log": "1.0.0"
- },
- "suggest": {
- "ext-proctitle": "Allows php-resque to rename the title of UNIX processes to show the status of a worker.",
- "ext-redis": "Native PHP extension for Redis connectivity. Credis will automatically utilize when available."
- },
- "require-dev": {
- "phpunit/phpunit": "3.7.*"
- },
- "bin": [
- "bin/resque"
- ],
- "autoload": {
- "psr-0": {
- "Resque": "lib"
- }
- }
+ "name": "spiritdead/php-resque",
+ "type": "library",
+ "description": "Redis backed library for creating background jobs and processing them later. Based on resque for Ruby.",
+ "keywords": [
+ "job",
+ "background",
+ "redis",
+ "resque"
+ ],
+ "homepage": "http://www.github.com/spiritdead/php-resque/",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Chris Boulton",
+ "email": "chris@bigcommerce.com"
+ },
+ {
+ "name": "Carlos Rodriguez",
+ "email": "mundofreakuc@gmail.com"
+ }
+ ],
+ "repositories": [
+ {
+ "type": "vcs",
+ "url": "https://github.com/chrisboulton/credis"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0",
+ "ext-pcntl": "*",
+ "colinmollenhour/credis": "~1.7",
+ "psr/log": "1.0.0"
+ },
+ "suggest": {
+ "ext-proctitle": "Allows php-resque to rename the title of UNIX processes to show the status of a worker.",
+ "ext-redis": "Native PHP extension for Redis connectivity. Credis will automatically utilize when available."
+ },
+ "require-dev": {
+ "phpunit/phpunit": "3.7.*"
+ },
+ "bin": [
+ "bin/resque"
+ ],
+ "autoload": {
+ "psr-0": {
+ "Resque": "lib"
+ }
+ }
}
diff --git a/demo/bad_job.php b/demo/bad_job.php
index cd719cc2..83721b0f 100644
--- a/demo/bad_job.php
+++ b/demo/bad_job.php
@@ -1,8 +1,9 @@
isTracking()) {
- die("Resque is not tracking the status of this job.\n");
+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);
+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);
}
\ No newline at end of file
diff --git a/demo/init.php b/demo/init.php
index 9078bcda..a0828ac8 100644
--- a/demo/init.php
+++ b/demo/init.php
@@ -2,24 +2,24 @@
// Find and initialize Composer
// NOTE: You should NOT use this when developing against php-resque.
// The autoload code below is specifically for this demo.
-$files = array(
- __DIR__ . '/../../vendor/autoload.php',
- __DIR__ . '/../../../../autoload.php',
- __DIR__ . '/../vendor/autoload.php',
-);
+$files = [
+ __DIR__ . '/../../vendor/autoload.php',
+ __DIR__ . '/../../../../autoload.php',
+ __DIR__ . '/../vendor/autoload.php'
+];
$found = false;
foreach ($files as $file) {
- if (file_exists($file)) {
- require_once $file;
- break;
- }
+ if (file_exists($file)) {
+ require_once $file;
+ break;
+ }
}
if (!class_exists('Composer\Autoload\ClassLoader', false)) {
- die(
- 'You need to set up the project dependencies using the following commands:' . PHP_EOL .
- 'curl -s http://getcomposer.org/installer | php' . PHP_EOL .
- 'php composer.phar install' . PHP_EOL
- );
+ die(
+ 'You need to set up the project dependencies using the following commands:' . PHP_EOL .
+ 'curl -s http://getcomposer.org/installer | php' . PHP_EOL .
+ 'php composer.phar install' . PHP_EOL
+ );
}
\ No newline at end of file
diff --git a/demo/job.php b/demo/job.php
index ddda8932..d861ee9c 100644
--- a/demo/job.php
+++ b/demo/job.php
@@ -1,10 +1,11 @@
');
- sleep(1);
- fwrite(STDOUT, 'Job ended!' . PHP_EOL);
- }
+ sleep(1);
+ fwrite(STDOUT, 'Job ended!' . PHP_EOL);
+ }
}
\ No newline at end of file
diff --git a/demo/long_job.php b/demo/long_job.php
index 1cfe5cb0..47d0a2df 100644
--- a/demo/long_job.php
+++ b/demo/long_job.php
@@ -1,8 +1,9 @@
time(),
- 'array' => array(
- 'test' => 'test',
- ),
-);
+$args = [
+ 'time' => time(),
+ 'array' => [
+ 'test' => 'test'
+ ]
+];
if (empty($argv[2])) {
- $jobId = Resque::enqueue('default', $argv[1], $args, true);
+ $jobId = Resque::enqueue('default', $argv[1], $args, true);
} else {
- $jobId = Resque::enqueue($argv[1], $argv[2], $args, true);
+ $jobId = Resque::enqueue($argv[1], $argv[2], $args, true);
}
-echo "Queued job ".$jobId."\n\n";
+echo "Queued job " . $jobId . "\n\n";
diff --git a/extras/sample-plugin.php b/extras/sample-plugin.php
index e70dffde..0779bf41 100644
--- a/extras/sample-plugin.php
+++ b/extras/sample-plugin.php
@@ -1,49 +1,49 @@
queues(false)) . "\n";
- }
-
- public static function beforeFork($job)
- {
- echo "Just about to fork to run " . $job;
- }
-
- public static function afterFork($job)
- {
- echo "Forked to run " . $job . ". This is the child process.\n";
- }
-
- public static function beforePerform($job)
- {
- echo "Cancelling " . $job . "\n";
- // throw new Resque_Job_DontPerform;
- }
-
- public static function afterPerform($job)
- {
- echo "Just performed " . $job . "\n";
- }
-
- public static function onFailure($exception, $job)
- {
- echo $job . " threw an exception:\n" . $exception;
- }
+ public static function afterEnqueue($class, $arguments)
+ {
+ echo "Job was queued for " . $class . ". Arguments:";
+ print_r($arguments);
+ }
+
+ public static function beforeFirstFork($worker)
+ {
+ echo "Worker started. Listening on queues: " . implode(', ', $worker->queues(false)) . "\n";
+ }
+
+ public static function beforeFork($job)
+ {
+ echo "Just about to fork to run " . $job;
+ }
+
+ public static function afterFork($job)
+ {
+ echo "Forked to run " . $job . ". This is the child process.\n";
+ }
+
+ public static function beforePerform($job)
+ {
+ echo "Cancelling " . $job . "\n";
+ // throw new Resque_Job_DontPerform;
+ }
+
+ public static function afterPerform($job)
+ {
+ echo "Just performed " . $job . "\n";
+ }
+
+ public static function onFailure($exception, $job)
+ {
+ echo $job . " threw an exception:\n" . $exception;
+ }
}
\ No newline at end of file
diff --git a/lib/Resque.php b/lib/Resque.php
index d03b2ecf..5e0e4530 100644
--- a/lib/Resque.php
+++ b/lib/Resque.php
@@ -1,379 +1,380 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque
{
- const VERSION = '1.2';
+ const VERSION = '1.2';
const DEFAULT_INTERVAL = 5;
- /**
- * @var Resque_Redis Instance of Resque_Redis that talks to redis.
- */
- public static $redis = null;
-
- /**
- * @var mixed Host/port conbination separated by a colon, or a nested
- * array of server swith host/port pairs
- */
- protected static $redisServer = null;
-
- /**
- * @var int ID of Redis database to select.
- */
- protected static $redisDatabase = 0;
-
- /**
- * Given a host/port combination separated by a colon, set it as
- * the redis server that Resque will talk to.
- *
- * @param mixed $server Host/port combination separated by a colon, DSN-formatted URI, or
- * a callable that receives the configured database ID
- * and returns a Resque_Redis instance, or
- * a nested array of servers with host/port pairs.
- * @param int $database
- */
- public static function setBackend($server, $database = 0)
- {
- self::$redisServer = $server;
- self::$redisDatabase = $database;
- self::$redis = null;
- }
-
- /**
- * Return an instance of the Resque_Redis class instantiated for Resque.
- *
- * @return Resque_Redis Instance of Resque_Redis.
- */
- public static function redis()
- {
- if (self::$redis !== null) {
- return self::$redis;
- }
-
- if (is_callable(self::$redisServer)) {
- self::$redis = call_user_func(self::$redisServer, self::$redisDatabase);
- } else {
- self::$redis = new Resque_Redis(self::$redisServer, self::$redisDatabase);
- }
-
- return self::$redis;
- }
-
- /**
- * fork() helper method for php-resque that handles issues PHP socket
- * and phpredis have with passing around sockets between child/parent
- * processes.
- *
- * Will close connection to Redis before forking.
- *
- * @return int Return vars as per pcntl_fork(). False if pcntl_fork is unavailable
- */
- public static function fork()
- {
- if(!function_exists('pcntl_fork')) {
- return false;
- }
-
- // Close the connection to Redis before forking.
- // This is a workaround for issues phpredis has.
- self::$redis = null;
-
- $pid = pcntl_fork();
- if($pid === -1) {
- throw new RuntimeException('Unable to fork child worker.');
- }
-
- return $pid;
- }
-
- /**
- * Push a job to the end of a specific queue. If the queue does not
- * exist, then create it as well.
- *
- * @param string $queue The name of the queue to add the job to.
- * @param array $item Job description as an array to be JSON encoded.
- */
- public static function push($queue, $item)
- {
- $encodedItem = json_encode($item);
- if ($encodedItem === false) {
- return false;
- }
- self::redis()->sadd('queues', $queue);
- $length = self::redis()->rpush('queue:' . $queue, $encodedItem);
- if ($length < 1) {
- return false;
- }
- return true;
- }
-
- /**
- * Pop an item off the end of the specified queue, decode it and
- * return it.
- *
- * @param string $queue The name of the queue to fetch an item from.
- * @return array Decoded item from the queue.
- */
- public static function pop($queue)
- {
+ /**
+ * @var Resque_Redis Instance of Resque_Redis that talks to redis.
+ */
+ public static $redis = null;
+
+ /**
+ * @var mixed Host/port conbination separated by a colon, or a nested
+ * array of server swith host/port pairs
+ */
+ protected static $redisServer = null;
+
+ /**
+ * @var int ID of Redis database to select.
+ */
+ protected static $redisDatabase = 0;
+
+ /**
+ * Given a host/port combination separated by a colon, set it as
+ * the redis server that Resque will talk to.
+ *
+ * @param mixed $server Host/port combination separated by a colon, DSN-formatted URI, or
+ * a callable that receives the configured database ID
+ * and returns a Resque_Redis instance, or
+ * a nested array of servers with host/port pairs.
+ * @param int $database
+ */
+ public static function setBackend($server, $database = 0)
+ {
+ self::$redisServer = $server;
+ self::$redisDatabase = $database;
+ self::$redis = null;
+ }
+
+ /**
+ * Return an instance of the Resque_Redis class instantiated for Resque.
+ *
+ * @return Resque_Redis Instance of Resque_Redis.
+ */
+ public static function redis()
+ {
+ if (self::$redis !== null) {
+ return self::$redis;
+ }
+
+ if (is_callable(self::$redisServer)) {
+ self::$redis = call_user_func(self::$redisServer, self::$redisDatabase);
+ } else {
+ self::$redis = new Resque_Redis(self::$redisServer, self::$redisDatabase);
+ }
+
+ return self::$redis;
+ }
+
+ /**
+ * fork() helper method for php-resque that handles issues PHP socket
+ * and phpredis have with passing around sockets between child/parent
+ * processes.
+ *
+ * Will close connection to Redis before forking.
+ *
+ * @return int Return vars as per pcntl_fork(). False if pcntl_fork is unavailable
+ */
+ public static function fork()
+ {
+ if (!function_exists('pcntl_fork')) {
+ return false;
+ }
+
+ // Close the connection to Redis before forking.
+ // This is a workaround for issues phpredis has.
+ self::$redis = null;
+
+ $pid = pcntl_fork();
+ if ($pid === -1) {
+ throw new RuntimeException('Unable to fork child worker.');
+ }
+
+ return $pid;
+ }
+
+ /**
+ * Push a job to the end of a specific queue. If the queue does not
+ * exist, then create it as well.
+ *
+ * @param string $queue The name of the queue to add the job to.
+ * @param array $item Job description as an array to be JSON encoded.
+ */
+ public static function push($queue, $item)
+ {
+ $encodedItem = json_encode($item);
+ if ($encodedItem === false) {
+ return false;
+ }
+ self::redis()->sadd('queues', $queue);
+ $length = self::redis()->rpush('queue:' . $queue, $encodedItem);
+ if ($length < 1) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Pop an item off the end of the specified queue, decode it and
+ * return it.
+ *
+ * @param string $queue The name of the queue to fetch an item from.
+ * @return array Decoded item from the queue.
+ */
+ public static function pop($queue)
+ {
$item = self::redis()->lpop('queue:' . $queue);
- if(!$item) {
- return;
- }
-
- return json_decode($item, true);
- }
-
- /**
- * Remove items of the specified queue
- *
- * @param string $queue The name of the queue to fetch an item from.
- * @param array $items
- * @return integer number of deleted items
- */
- public static function dequeue($queue, $items = Array())
- {
- if(count($items) > 0) {
- return self::removeItems($queue, $items);
- } else {
- return self::removeList($queue);
- }
- }
-
- /**
- * Remove specified queue
- *
- * @param string $queue The name of the queue to remove.
- * @return integer Number of deleted items
- */
- public static function removeQueue($queue)
- {
- $num = self::removeList($queue);
- self::redis()->srem('queues', $queue);
- return $num;
- }
-
- /**
- * Pop an item off the end of the specified queues, using blocking list pop,
- * decode it and return it.
- *
- * @param array $queues
- * @param int $timeout
- * @return null|array Decoded item from the queue.
- */
- public static function blpop(array $queues, $timeout)
- {
- $list = array();
- foreach($queues AS $queue) {
- $list[] = 'queue:' . $queue;
- }
-
- $item = self::redis()->blpop($list, (int)$timeout);
-
- if(!$item) {
- return;
- }
-
- /**
- * Normally the Resque_Redis class returns queue names without the prefix
- * But the blpop is a bit different. It returns the name as prefix:queue:name
- * So we need to strip off the prefix:queue: part
- */
- $queue = substr($item[0], strlen(self::redis()->getPrefix() . 'queue:'));
-
- return array(
- 'queue' => $queue,
- 'payload' => json_decode($item[1], true)
- );
- }
-
- /**
- * Return the size (number of pending jobs) of the specified queue.
- *
- * @param string $queue name of the queue to be checked for pending jobs
- *
- * @return int The size of the queue.
- */
- public static function size($queue)
- {
- return self::redis()->llen('queue:' . $queue);
- }
-
- /**
- * 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 = array(
- 'class' => $class,
- 'args' => $args,
- 'queue' => $queue,
- 'id' => $id,
- );
- try {
- Resque_Event::trigger('beforeEnqueue', $hookParams);
- }
- catch(Resque_Job_DontCreate $e) {
- return false;
- }
-
- Resque_Job::create($queue, $class, $args, $trackStatus, $id);
- Resque_Event::trigger('afterEnqueue', $hookParams);
-
- return $id;
- }
-
- /**
- * Reserve and return the next available job in the specified queue.
- *
- * @param string $queue Queue to fetch next available job from.
- * @return Resque_Job Instance of Resque_Job to be processed, false if none or error.
- */
- public static function reserve($queue)
- {
- return Resque_Job::reserve($queue);
- }
-
- /**
- * Get an array of all known queues.
- *
- * @return array Array of queues.
- */
- public static function queues()
- {
- $queues = self::redis()->smembers('queues');
- if(!is_array($queues)) {
- $queues = array();
- }
- return $queues;
- }
-
- /**
- * Remove Items from the queue
- * Safely moving each item to a temporary queue before processing it
- * If the Job matches, counts otherwise puts it in a requeue_queue
- * which at the end eventually be copied back into the original queue
- *
- * @private
- *
- * @param string $queue The name of the queue
- * @param array $items
- * @return integer number of deleted items
- */
- private static function removeItems($queue, $items = Array())
- {
- $counter = 0;
- $originalQueue = 'queue:'. $queue;
- $tempQueue = $originalQueue. ':temp:'. time();
- $requeueQueue = $tempQueue. ':requeue';
-
- // move each item from original queue to temp queue and process it
- $finished = false;
- while (!$finished) {
- $string = self::redis()->rpoplpush($originalQueue, self::redis()->getPrefix() . $tempQueue);
-
- if (!empty($string)) {
- if(self::matchItem($string, $items)) {
- self::redis()->rpop($tempQueue);
- $counter++;
- } else {
- self::redis()->rpoplpush($tempQueue, self::redis()->getPrefix() . $requeueQueue);
- }
- } else {
- $finished = true;
- }
- }
-
- // move back from temp queue to original queue
- $finished = false;
- while (!$finished) {
- $string = self::redis()->rpoplpush($requeueQueue, self::redis()->getPrefix() .$originalQueue);
- if (empty($string)) {
- $finished = true;
- }
- }
-
- // remove temp queue and requeue queue
- self::redis()->del($requeueQueue);
- self::redis()->del($tempQueue);
-
- return $counter;
- }
-
- /**
- * matching item
- * item can be ['class'] or ['class' => 'id'] or ['class' => {:foo => 1, :bar => 2}]
- * @private
- *
- * @params string $string redis result in json
- * @params $items
- *
- * @return (bool)
- */
- private static function matchItem($string, $items)
- {
- $decoded = json_decode($string, true);
-
- foreach($items as $key => $val) {
- # class name only ex: item[0] = ['class']
- if (is_numeric($key)) {
- if($decoded['class'] == $val) {
- return true;
- }
- # class name with args , example: item[0] = ['class' => {'foo' => 1, 'bar' => 2}]
- } elseif (is_array($val)) {
- $decodedArgs = (array)$decoded['args'][0];
- if ($decoded['class'] == $key &&
- count($decodedArgs) > 0 && count(array_diff($decodedArgs, $val)) == 0) {
- return true;
- }
- # class name with ID, example: item[0] = ['class' => 'id']
- } else {
- if ($decoded['class'] == $key && $decoded['id'] == $val) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Remove List
- *
- * @private
- *
- * @params string $queue the name of the queue
- * @return integer number of deleted items belongs to this list
- */
- private static function removeList($queue)
- {
- $counter = self::size($queue);
- $result = self::redis()->del('queue:' . $queue);
- return ($result == 1) ? $counter : 0;
- }
-
- /*
- * Generate an identifier to attach to a job for status tracking.
- *
- * @return string
- */
- public static function generateJobId()
- {
- return md5(uniqid('', true));
- }
+ if (!$item) {
+ return;
+ }
+
+ return json_decode($item, true);
+ }
+
+ /**
+ * Remove items of the specified queue
+ *
+ * @param string $queue The name of the queue to fetch an item from.
+ * @param array $items
+ * @return integer number of deleted items
+ */
+ public static function dequeue($queue, $items = [])
+ {
+ if (count($items) > 0) {
+ return self::removeItems($queue, $items);
+ } else {
+ return self::removeList($queue);
+ }
+ }
+
+ /**
+ * Remove specified queue
+ *
+ * @param string $queue The name of the queue to remove.
+ * @return integer Number of deleted items
+ */
+ public static function removeQueue($queue)
+ {
+ $num = self::removeList($queue);
+ self::redis()->srem('queues', $queue);
+ return $num;
+ }
+
+ /**
+ * Pop an item off the end of the specified queues, using blocking list pop,
+ * decode it and return it.
+ *
+ * @param array $queues
+ * @param int $timeout
+ * @return null|array Decoded item from the queue.
+ */
+ public static function blpop(array $queues, $timeout)
+ {
+ $list = [];
+ foreach ($queues AS $queue) {
+ $list[] = 'queue:' . $queue;
+ }
+
+ $item = self::redis()->blpop($list, (int)$timeout);
+
+ if (!$item) {
+ return null;
+ }
+
+ /**
+ * Normally the Resque_Redis class returns queue names without the prefix
+ * But the blpop is a bit different. It returns the name as prefix:queue:name
+ * So we need to strip off the prefix:queue: part
+ */
+ $queue = substr($item[0], strlen(self::redis()->getPrefix() . 'queue:'));
+
+ return [
+ 'queue' => $queue,
+ 'payload' => json_decode($item[1], true)
+ ];
+ }
+
+ /**
+ * Return the size (number of pending jobs) of the specified queue.
+ *
+ * @param string $queue name of the queue to be checked for pending jobs
+ *
+ * @return int The size of the queue.
+ */
+ public static function size($queue)
+ {
+ return self::redis()->llen('queue:' . $queue);
+ }
+
+ /**
+ * 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 {
+ Resque_Event::trigger('beforeEnqueue', $hookParams);
+ } catch (Resque_Job_DontCreate $e) {
+ return false;
+ }
+
+ Resque_Job::create($queue, $class, $args, $trackStatus, $id);
+ Resque_Event::trigger('afterEnqueue', $hookParams);
+
+ return $id;
+ }
+
+ /**
+ * Reserve and return the next available job in the specified queue.
+ *
+ * @param string $queue Queue to fetch next available job from.
+ * @return Resque_Job Instance of Resque_Job to be processed, false if none or error.
+ */
+ public static function reserve($queue)
+ {
+ return Resque_Job::reserve($queue);
+ }
+
+ /**
+ * Get an array of all known queues.
+ *
+ * @return array Array of queues.
+ */
+ public static function queues()
+ {
+ $queues = self::redis()->smembers('queues');
+ if (!is_array($queues)) {
+ $queues = [];
+ }
+ return $queues;
+ }
+
+ /**
+ * Remove Items from the queue
+ * Safely moving each item to a temporary queue before processing it
+ * If the Job matches, counts otherwise puts it in a requeue_queue
+ * which at the end eventually be copied back into the original queue
+ *
+ * @private
+ *
+ * @param string $queue The name of the queue
+ * @param array $items
+ * @return integer number of deleted items
+ */
+ private static function removeItems($queue, $items = [])
+ {
+ $counter = 0;
+ $originalQueue = 'queue:' . $queue;
+ $tempQueue = $originalQueue . ':temp:' . time();
+ $requeueQueue = $tempQueue . ':requeue';
+
+ // move each item from original queue to temp queue and process it
+ $finished = false;
+ while (!$finished) {
+ $string = self::redis()->rpoplpush($originalQueue, self::redis()->getPrefix() . $tempQueue);
+
+ if (!empty($string)) {
+ if (self::matchItem($string, $items)) {
+ self::redis()->rpop($tempQueue);
+ $counter++;
+ } else {
+ self::redis()->rpoplpush($tempQueue, self::redis()->getPrefix() . $requeueQueue);
+ }
+ } else {
+ $finished = true;
+ }
+ }
+
+ // move back from temp queue to original queue
+ $finished = false;
+ while (!$finished) {
+ $string = self::redis()->rpoplpush($requeueQueue, self::redis()->getPrefix() . $originalQueue);
+ if (empty($string)) {
+ $finished = true;
+ }
+ }
+
+ // remove temp queue and requeue queue
+ self::redis()->del($requeueQueue);
+ self::redis()->del($tempQueue);
+
+ return $counter;
+ }
+
+ /**
+ * matching item
+ * item can be ['class'] or ['class' => 'id'] or ['class' => {:foo => 1, :bar => 2}]
+ * @private
+ *
+ * @params string $string redis result in json
+ * @params $items
+ *
+ * @return (bool)
+ */
+ private static function matchItem($string, $items)
+ {
+ $decoded = json_decode($string, true);
+
+ foreach ($items as $key => $val) {
+ # class name only ex: item[0] = ['class']
+ if (is_numeric($key)) {
+ if ($decoded['class'] == $val) {
+ return true;
+ }
+ # class name with args , example: item[0] = ['class' => {'foo' => 1, 'bar' => 2}]
+ } elseif (is_array($val)) {
+ $decodedArgs = (array)$decoded['args'][0];
+ if ($decoded['class'] == $key &&
+ count($decodedArgs) > 0 && count(array_diff($decodedArgs, $val)) == 0
+ ) {
+ return true;
+ }
+ # class name with ID, example: item[0] = ['class' => 'id']
+ } else {
+ if ($decoded['class'] == $key && $decoded['id'] == $val) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remove List
+ *
+ * @private
+ *
+ * @params string $queue the name of the queue
+ * @return integer number of deleted items belongs to this list
+ */
+ private static function removeList($queue)
+ {
+ $counter = self::size($queue);
+ $result = self::redis()->del('queue:' . $queue);
+ return ($result == 1) ? $counter : 0;
+ }
+
+ /*
+ * Generate an identifier to attach to a job for status tracking.
+ *
+ * @return string
+ */
+ public static function generateJobId()
+ {
+ return md5(uniqid('', true));
+ }
}
diff --git a/lib/Resque/Event.php b/lib/Resque/Event.php
index 20072ff9..b570ff45 100644
--- a/lib/Resque/Event.php
+++ b/lib/Resque/Event.php
@@ -1,88 +1,89 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Event
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Event
{
- /**
- * @var array Array containing all registered callbacks, indexked by event name.
- */
- private static $events = array();
+ /**
+ * @var array Array containing all registered callbacks, indexked by event name.
+ */
+ private static $events = [];
+
+ /**
+ * Raise a given event with the supplied data.
+ *
+ * @param string $event Name of event to be raised.
+ * @param mixed $data Optional, any data that should be passed to each callback.
+ * @return true
+ */
+ public static function trigger($event, $data = null)
+ {
+ if (!is_array($data)) {
+ $data = [$data];
+ }
+
+ if (empty(self::$events[$event])) {
+ return true;
+ }
+
+ foreach (self::$events[$event] as $callback) {
+ if (!is_callable($callback)) {
+ continue;
+ }
+ call_user_func_array($callback, $data);
+ }
+
+ return true;
+ }
+
+ /**
+ * Listen in on a given event to have a specified callback fired.
+ *
+ * @param string $event Name of event to listen on.
+ * @param mixed $callback Any callback callable by call_user_func_array.
+ * @return true
+ */
+ public static function listen($event, $callback)
+ {
+ if (!isset(self::$events[$event])) {
+ self::$events[$event] = [];
+ }
+
+ self::$events[$event][] = $callback;
+ return true;
+ }
+
+ /**
+ * Stop a given callback from listening on a specific event.
+ *
+ * @param string $event Name of event.
+ * @param mixed $callback The callback as defined when listen() was called.
+ * @return true
+ */
+ public static function stopListening($event, $callback)
+ {
+ if (!isset(self::$events[$event])) {
+ return true;
+ }
+
+ $key = array_search($callback, self::$events[$event]);
+ if ($key !== false) {
+ unset(self::$events[$event][$key]);
+ }
- /**
- * Raise a given event with the supplied data.
- *
- * @param string $event Name of event to be raised.
- * @param mixed $data Optional, any data that should be passed to each callback.
- * @return true
- */
- public static function trigger($event, $data = null)
- {
- if (!is_array($data)) {
- $data = array($data);
- }
+ return true;
+ }
- if (empty(self::$events[$event])) {
- return true;
- }
-
- foreach (self::$events[$event] as $callback) {
- if (!is_callable($callback)) {
- continue;
- }
- call_user_func_array($callback, $data);
- }
-
- return true;
- }
-
- /**
- * Listen in on a given event to have a specified callback fired.
- *
- * @param string $event Name of event to listen on.
- * @param mixed $callback Any callback callable by call_user_func_array.
- * @return true
- */
- public static function listen($event, $callback)
- {
- if (!isset(self::$events[$event])) {
- self::$events[$event] = array();
- }
-
- self::$events[$event][] = $callback;
- return true;
- }
-
- /**
- * Stop a given callback from listening on a specific event.
- *
- * @param string $event Name of event.
- * @param mixed $callback The callback as defined when listen() was called.
- * @return true
- */
- public static function stopListening($event, $callback)
- {
- if (!isset(self::$events[$event])) {
- return true;
- }
-
- $key = array_search($callback, self::$events[$event]);
- if ($key !== false) {
- unset(self::$events[$event][$key]);
- }
-
- return true;
- }
-
- /**
- * Call all registered listeners.
- */
- public static function clearListeners()
- {
- self::$events = array();
- }
+ /**
+ * Call all registered listeners.
+ */
+ public static function clearListeners()
+ {
+ self::$events = [];
+ }
}
diff --git a/lib/Resque/Exception.php b/lib/Resque/Exception.php
index 01217c38..a20e2683 100644
--- a/lib/Resque/Exception.php
+++ b/lib/Resque/Exception.php
@@ -1,10 +1,11 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Exception extends Exception
{
diff --git a/lib/Resque/Failure.php b/lib/Resque/Failure.php
index deb678f9..e0e36fbc 100644
--- a/lib/Resque/Failure.php
+++ b/lib/Resque/Failure.php
@@ -3,54 +3,54 @@
/**
* Failed Resque job.
*
- * @package Resque/Failure
- * @author Chris Boulton
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Failure
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Failure
{
- /**
- * @var string Class name representing the backend to pass failed jobs off to.
- */
- private static $backend;
+ /**
+ * @var string Class name representing the backend to pass failed jobs off to.
+ */
+ private static $backend;
- /**
- * Create a new failed job on the backend.
- *
- * @param object $payload The contents of the job that has just failed.
- * @param \Exception $exception The exception generated when the job failed to run.
- * @param \Resque_Worker $worker Instance of Resque_Worker that was running this job when it failed.
- * @param string $queue The name of the queue that this job was fetched from.
- */
- public static function create($payload, Exception $exception, Resque_Worker $worker, $queue)
- {
- $backend = self::getBackend();
- new $backend($payload, $exception, $worker, $queue);
- }
+ /**
+ * Create a new failed job on the backend.
+ *
+ * @param object $payload The contents of the job that has just failed.
+ * @param \Exception $exception The exception generated when the job failed to run.
+ * @param \Resque_Worker $worker Instance of Resque_Worker that was running this job when it failed.
+ * @param string $queue The name of the queue that this job was fetched from.
+ */
+ public static function create($payload, Exception $exception, Resque_Worker $worker, $queue)
+ {
+ $backend = self::getBackend();
+ new $backend($payload, $exception, $worker, $queue);
+ }
- /**
- * Return an instance of the backend for saving job failures.
- *
- * @return object Instance of backend object.
- */
- public static function getBackend()
- {
- if(self::$backend === null) {
- self::$backend = 'Resque_Failure_Redis';
- }
+ /**
+ * Return an instance of the backend for saving job failures.
+ *
+ * @return object Instance of backend object.
+ */
+ public static function getBackend()
+ {
+ if (self::$backend === null) {
+ self::$backend = 'Resque_Failure_Redis';
+ }
- return self::$backend;
- }
+ return self::$backend;
+ }
- /**
- * Set the backend to use for raised job failures. The supplied backend
- * should be the name of a class to be instantiated when a job fails.
- * It is your responsibility to have the backend class loaded (or autoloaded)
- *
- * @param string $backend The class name of the backend to pipe failures to.
- */
- public static function setBackend($backend)
- {
- self::$backend = $backend;
- }
+ /**
+ * Set the backend to use for raised job failures. The supplied backend
+ * should be the name of a class to be instantiated when a job fails.
+ * It is your responsibility to have the backend class loaded (or autoloaded)
+ *
+ * @param string $backend The class name of the backend to pipe failures to.
+ */
+ public static function setBackend($backend)
+ {
+ self::$backend = $backend;
+ }
}
\ No newline at end of file
diff --git a/lib/Resque/Failure/Interface.php b/lib/Resque/Failure/Interface.php
index 74de9e7b..d6da0e25 100644
--- a/lib/Resque/Failure/Interface.php
+++ b/lib/Resque/Failure/Interface.php
@@ -1,20 +1,21 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Failure
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
interface Resque_Failure_Interface
{
- /**
- * 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);
+ /**
+ * 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);
}
diff --git a/lib/Resque/Failure/Redis.php b/lib/Resque/Failure/Redis.php
index 69d68724..6f342e30 100644
--- a/lib/Resque/Failure/Redis.php
+++ b/lib/Resque/Failure/Redis.php
@@ -1,33 +1,33 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Failure
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
-
class Resque_Failure_Redis implements Resque_Failure_Interface
{
- /**
- * 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);
- }
+ /**
+ * 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);
+ }
}
diff --git a/lib/Resque/Job.php b/lib/Resque/Job.php
index 8508f766..c7674adf 100755
--- a/lib/Resque/Job.php
+++ b/lib/Resque/Job.php
@@ -1,280 +1,278 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Job
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Job
{
- /**
- * @var string The name of the queue that this job belongs to.
- */
- public $queue;
-
- /**
- * @var Resque_Worker Instance of the Resque worker running this job.
- */
- public $worker;
-
- /**
- * @var array Array containing details of the job.
- */
- public $payload;
-
- /**
- * @var object|Resque_JobInterface Instance of the class performing work for this job.
- */
- private $instance;
-
- /**
- * @var Resque_Job_FactoryInterface
- */
- private $jobFactory;
-
- /**
- * Instantiate a new instance of a job.
- *
- * @param string $queue The queue that the job belongs to.
- * @param array $payload array containing details of the job.
- */
- public function __construct($queue, $payload)
- {
- $this->queue = $queue;
- $this->payload = $payload;
- }
-
- /**
- * 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 $monitor Set to true to be able to monitor the status of a job.
- * @param string $id Unique identifier for tracking the job. Generated if not supplied.
- *
- * @return string
- * @throws \InvalidArgumentException
- */
- public static function create($queue, $class, $args = null, $monitor = false, $id = null)
- {
- if (is_null($id)) {
- $id = Resque::generateJobId();
- }
-
- if($args !== null && !is_array($args)) {
- throw new InvalidArgumentException(
- 'Supplied $args must be an array.'
- );
- }
- Resque::push($queue, array(
- 'class' => $class,
- 'args' => array($args),
- 'id' => $id,
- 'queue_time' => microtime(true),
- ));
-
- if($monitor) {
- Resque_Job_Status::create($id);
- }
-
- return $id;
- }
-
- /**
- * Find the next available job from the specified queue and return an
- * instance of Resque_Job for it.
- *
- * @param string $queue The name of the queue to check for a job in.
- * @return false|object Null when there aren't any waiting jobs, instance of Resque_Job when a job was found.
- */
- public static function reserve($queue)
- {
- $payload = Resque::pop($queue);
- if(!is_array($payload)) {
- return false;
- }
-
- return new Resque_Job($queue, $payload);
- }
-
- /**
- * Find the next available job from the specified queues using blocking list pop
- * and return an instance of Resque_Job for it.
- *
- * @param array $queues
- * @param int $timeout
- * @return false|object Null when there aren't any waiting jobs, instance of Resque_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 Resque_Job($item['queue'], $item['payload']);
- }
-
- /**
- * Update the status of the current job.
- *
- * @param int $status Status constant from Resque_Job_Status indicating the current status of a job.
- */
- public function updateStatus($status)
- {
- if(empty($this->payload['id'])) {
- return;
- }
-
- $statusInstance = new Resque_Job_Status($this->payload['id']);
- $statusInstance->update($status);
- }
-
- /**
- * Return the status of the current job.
- *
- * @return int The status of the job as one of the Resque_Job_Status constants.
- */
- public function getStatus()
- {
- $status = new Resque_Job_Status($this->payload['id']);
- return $status->get();
- }
-
- /**
- * Get the arguments supplied to this job.
- *
- * @return array Array of arguments.
- */
- public function getArguments()
- {
- if (!isset($this->payload['args'])) {
- return array();
- }
-
- return $this->payload['args'][0];
- }
-
- /**
- * Get the instantiated object for this job that will be performing work.
- * @return Resque_JobInterface Instance of the object that this job belongs to.
- * @throws Resque_Exception
- */
- public function getInstance()
- {
- if (!is_null($this->instance)) {
- return $this->instance;
- }
+ /**
+ * @var string The name of the queue that this job belongs to.
+ */
+ public $queue;
+
+ /**
+ * @var Resque_Worker Instance of the Resque worker running this job.
+ */
+ public $worker;
+
+ /**
+ * @var array Array containing details of the job.
+ */
+ public $payload;
+
+ /**
+ * @var object|Resque_JobInterface Instance of the class performing work for this job.
+ */
+ private $instance;
+
+ /**
+ * @var Resque_Job_FactoryInterface
+ */
+ private $jobFactory;
+
+ /**
+ * Instantiate a new instance of a job.
+ *
+ * @param string $queue The queue that the job belongs to.
+ * @param array $payload array containing details of the job.
+ */
+ public function __construct($queue, $payload)
+ {
+ $this->queue = $queue;
+ $this->payload = $payload;
+ }
+
+ /**
+ * 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 $monitor Set to true to be able to monitor the status of a job.
+ * @param string $id Unique identifier for tracking the job. Generated if not supplied.
+ *
+ * @return string
+ * @throws \InvalidArgumentException
+ */
+ public static function create($queue, $class, $args = null, $monitor = false, $id = null)
+ {
+ if (is_null($id)) {
+ $id = Resque::generateJobId();
+ }
+
+ if ($args !== null && !is_array($args)) {
+ throw new InvalidArgumentException(
+ 'Supplied $args must be an array.'
+ );
+ }
+ Resque::push($queue, [
+ 'class' => $class,
+ 'args' => [$args],
+ 'id' => $id,
+ 'queue_time' => microtime(true)
+ ]);
+
+ if ($monitor) {
+ Resque_Job_Status::create($id);
+ }
+
+ return $id;
+ }
+
+ /**
+ * Find the next available job from the specified queue and return an
+ * instance of Resque_Job for it.
+ *
+ * @param string $queue The name of the queue to check for a job in.
+ * @return false|object Null when there aren't any waiting jobs, instance of Resque_Job when a job was found.
+ */
+ public static function reserve($queue)
+ {
+ $payload = Resque::pop($queue);
+ if (!is_array($payload)) {
+ return false;
+ }
+
+ return new Resque_Job($queue, $payload);
+ }
+
+ /**
+ * Find the next available job from the specified queues using blocking list pop
+ * and return an instance of Resque_Job for it.
+ *
+ * @param array $queues
+ * @param int $timeout
+ * @return false|object Null when there aren't any waiting jobs, instance of Resque_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 Resque_Job($item['queue'], $item['payload']);
+ }
+
+ /**
+ * Update the status of the current job.
+ *
+ * @param int $status Status constant from Resque_Job_Status indicating the current status of a job.
+ */
+ public function updateStatus($status)
+ {
+ if (empty($this->payload['id'])) {
+ return;
+ }
+
+ $statusInstance = new Resque_Job_Status($this->payload['id']);
+ $statusInstance->update($status);
+ }
+
+ /**
+ * Return the status of the current job.
+ *
+ * @return int The status of the job as one of the Resque_Job_Status constants.
+ */
+ public function getStatus()
+ {
+ $status = new Resque_Job_Status($this->payload['id']);
+ return $status->get();
+ }
+
+ /**
+ * Get the arguments supplied to this job.
+ *
+ * @return array Array of arguments.
+ */
+ public function getArguments()
+ {
+ if (!isset($this->payload['args'])) {
+ return [];
+ }
+
+ return $this->payload['args'][0];
+ }
+
+ /**
+ * Get the instantiated object for this job that will be performing work.
+ * @return Resque_JobInterface Instance of the object that this job belongs to.
+ * @throws Resque_Exception
+ */
+ public function getInstance()
+ {
+ if (!is_null($this->instance)) {
+ return $this->instance;
+ }
$this->instance = $this->getJobFactory()->create($this->payload['class'], $this->getArguments(), $this->queue);
$this->instance->job = $this;
return $this->instance;
- }
-
- /**
- * Actually execute a job by calling the perform method on the class
- * associated with the job with the supplied arguments.
- *
- * @return bool
- * @throws Resque_Exception When the job's class could not be found or it does not contain a perform method.
- */
- public function perform()
- {
- try {
- Resque_Event::trigger('beforePerform', $this);
-
- $instance = $this->getInstance();
- if(method_exists($instance, 'setUp')) {
- $instance->setUp();
- }
-
- $instance->perform();
-
- if(method_exists($instance, 'tearDown')) {
- $instance->tearDown();
- }
-
- Resque_Event::trigger('afterPerform', $this);
- }
- // beforePerform/setUp have said don't perform this job. Return.
- catch(Resque_Job_DontPerform $e) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Mark the current job as having failed.
- *
- * @param $exception
- */
- public function fail($exception)
- {
- Resque_Event::trigger('onFailure', array(
- 'exception' => $exception,
- 'job' => $this,
- ));
-
- $this->updateStatus(Resque_Job_Status::STATUS_FAILED);
- Resque_Failure::create(
- $this->payload,
- $exception,
- $this->worker,
- $this->queue
- );
- Resque_Stat::incr('failed');
- Resque_Stat::incr('failed:' . $this->worker);
- }
-
- /**
- * Re-queue the current job.
- * @return string
- */
- public function recreate()
- {
- $status = new Resque_Job_Status($this->payload['id']);
- $monitor = false;
- if($status->isTracking()) {
- $monitor = true;
- }
-
- return self::create($this->queue, $this->payload['class'], $this->getArguments(), $monitor);
- }
-
- /**
- * Generate a string representation used to describe the current job.
- *
- * @return string The string representation of the job.
- */
- public function __toString()
- {
- $name = array(
- 'Job{' . $this->queue .'}'
- );
- if(!empty($this->payload['id'])) {
- $name[] = 'ID: ' . $this->payload['id'];
- }
- $name[] = $this->payload['class'];
- if(!empty($this->payload['args'])) {
- $name[] = json_encode($this->payload['args']);
- }
- return '(' . implode(' | ', $name) . ')';
- }
-
- /**
- * @param Resque_Job_FactoryInterface $jobFactory
- * @return Resque_Job
- */
- public function setJobFactory(Resque_Job_FactoryInterface $jobFactory)
- {
- $this->jobFactory = $jobFactory;
-
- return $this;
- }
+ }
+
+ /**
+ * Actually execute a job by calling the perform method on the class
+ * associated with the job with the supplied arguments.
+ *
+ * @return bool
+ * @throws Resque_Exception When the job's class could not be found or it does not contain a perform method.
+ */
+ public function perform()
+ {
+ try {
+ Resque_Event::trigger('beforePerform', $this);
+
+ $instance = $this->getInstance();
+ if (method_exists($instance, 'setUp')) {
+ $instance->setUp();
+ }
+
+ $instance->perform();
+
+ if (method_exists($instance, 'tearDown')) {
+ $instance->tearDown();
+ }
+
+ Resque_Event::trigger('afterPerform', $this);
+ } // beforePerform/setUp have said don't perform this job. Return.
+ catch (Resque_Job_DontPerform $e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Mark the current job as having failed.
+ *
+ * @param $exception
+ */
+ public function fail($exception)
+ {
+ Resque_Event::trigger('onFailure', [
+ 'exception' => $exception,
+ 'job' => $this
+ ]);
+
+ $this->updateStatus(Resque_Job_Status::STATUS_FAILED);
+ Resque_Failure::create(
+ $this->payload,
+ $exception,
+ $this->worker,
+ $this->queue
+ );
+ Resque_Stat::incr('failed');
+ Resque_Stat::incr('failed:' . $this->worker);
+ }
+
+ /**
+ * Re-queue the current job.
+ * @return string
+ */
+ public function recreate()
+ {
+ $status = new Resque_Job_Status($this->payload['id']);
+ $monitor = false;
+ if ($status->isTracking()) {
+ $monitor = true;
+ }
+
+ return self::create($this->queue, $this->payload['class'], $this->getArguments(), $monitor);
+ }
+
+ /**
+ * Generate a string representation used to describe the current job.
+ *
+ * @return string The string representation of the job.
+ */
+ public function __toString()
+ {
+ $name = ['Job{' . $this->queue . '}'];
+ if (!empty($this->payload['id'])) {
+ $name[] = 'ID: ' . $this->payload['id'];
+ }
+ $name[] = $this->payload['class'];
+ if (!empty($this->payload['args'])) {
+ $name[] = json_encode($this->payload['args']);
+ }
+ return '(' . implode(' | ', $name) . ')';
+ }
+
+ /**
+ * @param Resque_Job_FactoryInterface $jobFactory
+ * @return Resque_Job
+ */
+ public function setJobFactory(Resque_Job_FactoryInterface $jobFactory)
+ {
+ $this->jobFactory = $jobFactory;
+
+ return $this;
+ }
/**
* @return Resque_Job_FactoryInterface
diff --git a/lib/Resque/Job/DirtyExitException.php b/lib/Resque/Job/DirtyExitException.php
index 108e0613..82a9232d 100644
--- a/lib/Resque/Job/DirtyExitException.php
+++ b/lib/Resque/Job/DirtyExitException.php
@@ -1,10 +1,11 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Job
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Job_DirtyExitException extends RuntimeException
{
diff --git a/lib/Resque/Job/DontCreate.php b/lib/Resque/Job/DontCreate.php
index 31c33cdc..2e24964f 100644
--- a/lib/Resque/Job/DontCreate.php
+++ b/lib/Resque/Job/DontCreate.php
@@ -1,10 +1,11 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Job
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Job_DontCreate extends Exception
{
diff --git a/lib/Resque/Job/DontPerform.php b/lib/Resque/Job/DontPerform.php
index 553327ff..c0cdef95 100644
--- a/lib/Resque/Job/DontPerform.php
+++ b/lib/Resque/Job/DontPerform.php
@@ -1,10 +1,11 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Job
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Job_DontPerform extends Exception
{
diff --git a/lib/Resque/Job/FactoryInterface.php b/lib/Resque/Job/FactoryInterface.php
index b8c102cf..a1203e14 100644
--- a/lib/Resque/Job/FactoryInterface.php
+++ b/lib/Resque/Job/FactoryInterface.php
@@ -2,11 +2,11 @@
interface Resque_Job_FactoryInterface
{
- /**
- * @param $className
- * @param array $args
- * @param $queue
- * @return Resque_JobInterface
- */
- public function create($className, $args, $queue);
+ /**
+ * @param $className
+ * @param array $args
+ * @param $queue
+ * @return Resque_JobInterface
+ */
+ public function create($className, $args, $queue);
}
diff --git a/lib/Resque/Job/Status.php b/lib/Resque/Job/Status.php
index 00fc40c5..61b5f9f9 100644
--- a/lib/Resque/Job/Status.php
+++ b/lib/Resque/Job/Status.php
@@ -1,142 +1,143 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Job
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Job_Status
{
- const STATUS_WAITING = 1;
- const STATUS_RUNNING = 2;
- const STATUS_FAILED = 3;
- const STATUS_COMPLETE = 4;
-
- /**
- * @var string The ID of the job this status class refers back to.
- */
- private $id;
-
- /**
- * @var mixed Cache variable if the status of this job is being monitored or not.
- * True/false when checked at least once or null if not checked yet.
- */
- private $isTracking = null;
-
- /**
- * @var array Array of statuses that are considered final/complete.
- */
- private static $completeStatuses = array(
- self::STATUS_FAILED,
- self::STATUS_COMPLETE
- );
-
- /**
- * Setup a new instance of the job monitor class for the supplied job ID.
- *
- * @param string $id The ID of the job to manage the status for.
- */
- public function __construct($id)
- {
- $this->id = $id;
- }
-
- /**
- * Create a new status monitor item for the supplied job ID. Will create
- * all necessary keys in Redis to monitor the status of a job.
- *
- * @param string $id The ID of the job to monitor the status of.
- */
- public static function create($id)
- {
- $statusPacket = array(
- 'status' => self::STATUS_WAITING,
- 'updated' => time(),
- 'started' => time(),
- );
- Resque::redis()->set('job:' . $id . ':status', json_encode($statusPacket));
- }
-
- /**
- * Check if we're actually checking the status of the loaded job status
- * instance.
- *
- * @return boolean True if the status is being monitored, false if not.
- */
- public function isTracking()
- {
- if($this->isTracking === false) {
- return false;
- }
-
- if(!Resque::redis()->exists((string)$this)) {
- $this->isTracking = false;
- return false;
- }
-
- $this->isTracking = true;
- return true;
- }
-
- /**
- * Update the status indicator for the current job with a new status.
- *
- * @param int The status of the job (see constants in Resque_Job_Status)
- */
- public function update($status)
- {
- if(!$this->isTracking()) {
- return;
- }
-
- $statusPacket = array(
- 'status' => $status,
- 'updated' => time(),
- );
- Resque::redis()->set((string)$this, json_encode($statusPacket));
-
- // Expire the status for completed jobs after 24 hours
- if(in_array($status, self::$completeStatuses)) {
- Resque::redis()->expire((string)$this, 86400);
- }
- }
-
- /**
- * Fetch the status for the job being monitored.
- *
- * @return mixed False if the status is not being monitored, otherwise the status as
- * as an integer, based on the Resque_Job_Status constants.
- */
- public function get()
- {
- if(!$this->isTracking()) {
- return false;
- }
-
- $statusPacket = json_decode(Resque::redis()->get((string)$this), true);
- if(!$statusPacket) {
- return false;
- }
-
- return $statusPacket['status'];
- }
-
- /**
- * Stop tracking the status of a job.
- */
- public function stop()
- {
- Resque::redis()->del((string)$this);
- }
-
- /**
- * Generate a string representation of this object.
- *
- * @return string String representation of the current job status class.
- */
- public function __toString()
- {
- return 'job:' . $this->id . ':status';
- }
+ const STATUS_WAITING = 1;
+ const STATUS_RUNNING = 2;
+ const STATUS_FAILED = 3;
+ const STATUS_COMPLETE = 4;
+
+ /**
+ * @var string The ID of the job this status class refers back to.
+ */
+ private $id;
+
+ /**
+ * @var mixed Cache variable if the status of this job is being monitored or not.
+ * True/false when checked at least once or null if not checked yet.
+ */
+ private $isTracking = null;
+
+ /**
+ * @var array Array of statuses that are considered final/complete.
+ */
+ private static $completeStatuses = [
+ self::STATUS_FAILED,
+ self::STATUS_COMPLETE
+ ];
+
+ /**
+ * Setup a new instance of the job monitor class for the supplied job ID.
+ *
+ * @param string $id The ID of the job to manage the status for.
+ */
+ public function __construct($id)
+ {
+ $this->id = $id;
+ }
+
+ /**
+ * Create a new status monitor item for the supplied job ID. Will create
+ * all necessary keys in Redis to monitor the status of a job.
+ *
+ * @param string $id The ID of the job to monitor the status of.
+ */
+ public static function create($id)
+ {
+ $statusPacket = [
+ 'status' => self::STATUS_WAITING,
+ 'updated' => time(),
+ 'started' => time()
+ ];
+ Resque::redis()->set('job:' . $id . ':status', json_encode($statusPacket));
+ }
+
+ /**
+ * Check if we're actually checking the status of the loaded job status
+ * instance.
+ *
+ * @return boolean True if the status is being monitored, false if not.
+ */
+ public function isTracking()
+ {
+ if ($this->isTracking === false) {
+ return false;
+ }
+
+ if (!Resque::redis()->exists((string)$this)) {
+ $this->isTracking = false;
+ return false;
+ }
+
+ $this->isTracking = true;
+ return true;
+ }
+
+ /**
+ * Update the status indicator for the current job with a new status.
+ *
+ * @param int The status of the job (see constants in Resque_Job_Status)
+ */
+ public function update($status)
+ {
+ if (!$this->isTracking()) {
+ return;
+ }
+
+ $statusPacket = [
+ 'status' => $status,
+ 'updated' => time()
+ ];
+ Resque::redis()->set((string)$this, json_encode($statusPacket));
+
+ // Expire the status for completed jobs after 24 hours
+ if (in_array($status, self::$completeStatuses)) {
+ Resque::redis()->expire((string)$this, 86400);
+ }
+ }
+
+ /**
+ * Fetch the status for the job being monitored.
+ *
+ * @return mixed False if the status is not being monitored, otherwise the status as
+ * as an integer, based on the Resque_Job_Status constants.
+ */
+ public function get()
+ {
+ if (!$this->isTracking()) {
+ return false;
+ }
+
+ $statusPacket = json_decode(Resque::redis()->get((string)$this), true);
+ if (!$statusPacket) {
+ return false;
+ }
+
+ return $statusPacket['status'];
+ }
+
+ /**
+ * Stop tracking the status of a job.
+ */
+ public function stop()
+ {
+ Resque::redis()->del((string)$this);
+ }
+
+ /**
+ * Generate a string representation of this object.
+ *
+ * @return string String representation of the current job status class.
+ */
+ public function __toString()
+ {
+ return 'job:' . $this->id . ':status';
+ }
}
diff --git a/lib/Resque/JobInterface.php b/lib/Resque/JobInterface.php
index be5891db..f31281dd 100644
--- a/lib/Resque/JobInterface.php
+++ b/lib/Resque/JobInterface.php
@@ -2,8 +2,8 @@
interface Resque_JobInterface
{
- /**
- * @return bool
- */
- public function perform();
+ /**
+ * @return bool
+ */
+ public function perform();
}
diff --git a/lib/Resque/Log.php b/lib/Resque/Log.php
index ce279cc6..b9518a25 100644
--- a/lib/Resque/Log.php
+++ b/lib/Resque/Log.php
@@ -1,62 +1,69 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Stat
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
-class Resque_Log extends Psr\Log\AbstractLogger
+class Resque_Log extends Psr\Log\AbstractLogger
{
- public $verbose;
+ public $verbose;
+
+ public $debug;
+
+ public function __construct($verbose = false, $debug = false)
+ {
+ $this->verbose = $verbose;
+ $this->debug = $debug;
+ }
- public function __construct($verbose = false) {
- $this->verbose = $verbose;
- }
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level PSR-3 log level constant, or equivalent string
+ * @param string $message Message to log, may contain a { placeholder }
+ * @param array $context Variables to replace { placeholder }
+ * @return null
+ */
+ public function log($level, $message, array $context = [])
+ {
+ if ($this->verbose) {
+ fwrite(
+ STDOUT,
+ '[' . $level . '] [' . strftime('%T %Y-%m-%d') . '] ' . $this->interpolate($message, $context) . PHP_EOL
+ );
+ return;
+ }
- /**
- * Logs with an arbitrary level.
- *
- * @param mixed $level PSR-3 log level constant, or equivalent string
- * @param string $message Message to log, may contain a { placeholder }
- * @param array $context Variables to replace { placeholder }
- * @return null
- */
- public function log($level, $message, array $context = array())
- {
- if ($this->verbose) {
- fwrite(
- STDOUT,
- '[' . $level . '] [' . strftime('%T %Y-%m-%d') . '] ' . $this->interpolate($message, $context) . PHP_EOL
- );
- return;
- }
+ if ($this->debug) {
+ if (!($level === Psr\Log\LogLevel::INFO || $level === Psr\Log\LogLevel::DEBUG)) {
+ fwrite(
+ STDOUT,
+ '[' . $level . '] ' . $this->interpolate($message, $context) . PHP_EOL
+ );
+ }
+ }
+ }
- if (!($level === Psr\Log\LogLevel::INFO || $level === Psr\Log\LogLevel::DEBUG)) {
- fwrite(
- STDOUT,
- '[' . $level . '] ' . $this->interpolate($message, $context) . PHP_EOL
- );
- }
- }
+ /**
+ * Fill placeholders with the provided context
+ * @author Jordi Boggiano j.boggiano@seld.be
+ *
+ * @param string $message Message to be logged
+ * @param array $context Array of variables to use in message
+ * @return string
+ */
+ public function interpolate($message, array $context = [])
+ {
+ // build a replacement array with braces around the context keys
+ $replace = [];
+ foreach ($context as $key => $val) {
+ $replace['{' . $key . '}'] = $val;
+ }
- /**
- * Fill placeholders with the provided context
- * @author Jordi Boggiano j.boggiano@seld.be
- *
- * @param string $message Message to be logged
- * @param array $context Array of variables to use in message
- * @return string
- */
- public function interpolate($message, array $context = array())
- {
- // build a replacement array with braces around the context keys
- $replace = array();
- foreach ($context as $key => $val) {
- $replace['{' . $key . '}'] = $val;
- }
-
- // interpolate replacement values into the message and return
- return strtr($message, $replace);
- }
+ // interpolate replacement values into the message and return
+ return strtr($message, $replace);
+ }
}
diff --git a/lib/Resque/Redis.php b/lib/Resque/Redis.php
index 153bd40e..79fe0907 100644
--- a/lib/Resque/Redis.php
+++ b/lib/Resque/Redis.php
@@ -1,270 +1,268 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Redis
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Redis
{
- /**
- * Redis namespace
- * @var string
- */
- private static $defaultNamespace = 'resque:';
+ /**
+ * Redis namespace
+ * @var string
+ */
+ private static $defaultNamespace = 'resque:';
- /**
- * A default host to connect to
- */
- const DEFAULT_HOST = 'localhost';
+ /**
+ * A default host to connect to
+ */
+ const DEFAULT_HOST = 'localhost';
- /**
- * The default Redis port
- */
- const DEFAULT_PORT = 6379;
+ /**
+ * The default Redis port
+ */
+ const DEFAULT_PORT = 6379;
- /**
- * The default Redis Database number
- */
- const DEFAULT_DATABASE = 0;
+ /**
+ * The default Redis Database number
+ */
+ const DEFAULT_DATABASE = 0;
- /**
- * @var array List of all commands in Redis that supply a key as their
- * first argument. Used to prefix keys with the Resque namespace.
- */
- private $keyCommands = array(
- 'exists',
- 'del',
- 'type',
- 'keys',
- 'expire',
- 'ttl',
- 'move',
- 'set',
- 'setex',
- 'get',
- 'getset',
- 'setnx',
- 'incr',
- 'incrby',
- 'decr',
- 'decrby',
- 'rpush',
- 'lpush',
- 'llen',
- 'lrange',
- 'ltrim',
- 'lindex',
- 'lset',
- 'lrem',
- 'lpop',
- 'blpop',
- 'rpop',
- 'sadd',
- 'srem',
- 'spop',
- 'scard',
- 'sismember',
- 'smembers',
- 'srandmember',
- 'zadd',
- 'zrem',
- 'zrange',
- 'zrevrange',
- 'zrangebyscore',
- 'zcard',
- 'zscore',
- 'zremrangebyscore',
- 'sort',
- 'rename',
- 'rpoplpush'
- );
- // sinterstore
- // sunion
- // sunionstore
- // sdiff
- // sdiffstore
- // sinter
- // smove
- // mget
- // msetnx
- // mset
- // renamenx
+ /**
+ * @var array List of all commands in Redis that supply a key as their
+ * first argument. Used to prefix keys with the Resque namespace.
+ */
+ private $keyCommands = [
+ 'exists',
+ 'del',
+ 'type',
+ 'keys',
+ 'expire',
+ 'ttl',
+ 'move',
+ 'set',
+ 'setex',
+ 'get',
+ 'getset',
+ 'setnx',
+ 'incr',
+ 'incrby',
+ 'decr',
+ 'decrby',
+ 'rpush',
+ 'lpush',
+ 'llen',
+ 'lrange',
+ 'ltrim',
+ 'lindex',
+ 'lset',
+ 'lrem',
+ 'lpop',
+ 'blpop',
+ 'rpop',
+ 'sadd',
+ 'srem',
+ 'spop',
+ 'scard',
+ 'sismember',
+ 'smembers',
+ 'srandmember',
+ 'zadd',
+ 'zrem',
+ 'zrange',
+ 'zrevrange',
+ 'zrangebyscore',
+ 'zcard',
+ 'zscore',
+ 'zremrangebyscore',
+ 'sort',
+ 'rename',
+ 'rpoplpush'
+ ];
+ // sinterstore
+ // sunion
+ // sunionstore
+ // sdiff
+ // sdiffstore
+ // sinter
+ // smove
+ // mget
+ // msetnx
+ // mset
+ // renamenx
- /**
- * Set Redis namespace (prefix) default: resque
- * @param string $namespace
- */
- public static function prefix($namespace)
- {
- if (substr($namespace, -1) !== ':' && $namespace != '') {
- $namespace .= ':';
- }
- self::$defaultNamespace = $namespace;
- }
+ /**
+ * Set Redis namespace (prefix) default: resque
+ * @param string $namespace
+ */
+ public static function prefix($namespace)
+ {
+ if (substr($namespace, -1) !== ':' && $namespace != '') {
+ $namespace .= ':';
+ }
+ self::$defaultNamespace = $namespace;
+ }
- /**
- * @param string|array $server A DSN or array
- * @param int $database A database number to select. However, if we find a valid database number in the DSN the
- * DSN-supplied value will be used instead and this parameter is ignored.
- * @param object $client Optional Credis_Cluster or Credis_Client instance instantiated by you
- */
+ /**
+ * @param string|array $server A DSN or array
+ * @param int $database A database number to select. However, if we find a valid database number in the DSN the
+ * DSN-supplied value will be used instead and this parameter is ignored.
+ * @param object $client Optional Credis_Cluster or Credis_Client instance instantiated by you
+ */
public function __construct($server, $database = null, $client = null)
- {
- try {
- if (is_array($server)) {
- $this->driver = new Credis_Cluster($server);
- }
- else if (is_object($client)) {
- $this->driver = $client;
- }
- else {
- list($host, $port, $dsnDatabase, $user, $password, $options) = self::parseDsn($server);
- // $user is not used, only $password
+ {
+ try {
+ if (is_array($server)) {
+ $this->driver = new Credis_Cluster($server);
+ } else {
+ if (is_object($client)) {
+ $this->driver = $client;
+ } else {
+ list($host, $port, $dsnDatabase, $user, $password, $options) = self::parseDsn($server);
+ // $user is not used, only $password
- // Look for known Credis_Client options
- $timeout = isset($options['timeout']) ? intval($options['timeout']) : null;
- $persistent = isset($options['persistent']) ? $options['persistent'] : '';
- $maxRetries = isset($options['max_connect_retries']) ? $options['max_connect_retries'] : 0;
+ // Look for known Credis_Client options
+ $timeout = isset($options['timeout']) ? intval($options['timeout']) : null;
+ $persistent = isset($options['persistent']) ? $options['persistent'] : '';
+ $maxRetries = isset($options['max_connect_retries']) ? $options['max_connect_retries'] : 0;
- $this->driver = new Credis_Client($host, $port, $timeout, $persistent);
- $this->driver->setMaxConnectRetries($maxRetries);
- if ($password){
- $this->driver->auth($password);
- }
+ $this->driver = new Credis_Client($host, $port, $timeout, $persistent);
+ $this->driver->setMaxConnectRetries($maxRetries);
+ if ($password) {
+ $this->driver->auth($password);
+ }
- // If we have found a database in our DSN, use it instead of the `$database`
- // value passed into the constructor.
- if ($dsnDatabase !== false) {
- $database = $dsnDatabase;
- }
- }
+ // If we have found a database in our DSN, use it instead of the `$database`
+ // value passed into the constructor.
+ if ($dsnDatabase !== false) {
+ $database = $dsnDatabase;
+ }
+ }
+ }
- if ($database !== null) {
- $this->driver->select($database);
- }
- }
- catch(CredisException $e) {
- throw new Resque_RedisException('Error communicating with Redis: ' . $e->getMessage(), 0, $e);
- }
- }
+ if ($database !== null) {
+ $this->driver->select($database);
+ }
+ } catch (CredisException $e) {
+ throw new Resque_RedisException('Error communicating with Redis: ' . $e->getMessage(), 0, $e);
+ }
+ }
- /**
- * Parse a DSN string, which can have one of the following formats:
- *
- * - host:port
- * - redis://user:pass@host:port/db?option1=val1&option2=val2
- * - tcp://user:pass@host:port/db?option1=val1&option2=val2
- * - unix:///path/to/redis.sock
- *
- * Note: the 'user' part of the DSN is not used.
- *
- * @param string $dsn A DSN string
- * @return array An array of DSN compotnents, with 'false' values for any unknown components. e.g.
- * [host, port, db, user, pass, options]
- */
- public static function parseDsn($dsn)
- {
- if ($dsn == '') {
- // Use a sensible default for an empty DNS string
- $dsn = 'redis://' . self::DEFAULT_HOST;
- }
- if(substr($dsn, 0, 7) === 'unix://') {
- return array(
- $dsn,
- null,
- false,
- null,
- null,
- null,
- );
- }
- $parts = parse_url($dsn);
+ /**
+ * Parse a DSN string, which can have one of the following formats:
+ *
+ * - host:port
+ * - redis://user:pass@host:port/db?option1=val1&option2=val2
+ * - tcp://user:pass@host:port/db?option1=val1&option2=val2
+ * - unix:///path/to/redis.sock
+ *
+ * Note: the 'user' part of the DSN is not used.
+ *
+ * @param string $dsn A DSN string
+ * @return array An array of DSN compotnents, with 'false' values for any unknown components. e.g.
+ * [host, port, db, user, pass, options]
+ */
+ public static function parseDsn($dsn)
+ {
+ if ($dsn == '') {
+ // Use a sensible default for an empty DNS string
+ $dsn = 'redis://' . self::DEFAULT_HOST;
+ }
+ if (substr($dsn, 0, 7) === 'unix://') {
+ return [
+ $dsn,
+ null,
+ false,
+ null,
+ null,
+ null
+ ];
+ }
+ $parts = parse_url($dsn);
- // Check the URI scheme
- $validSchemes = array('redis', 'tcp');
- if (isset($parts['scheme']) && ! in_array($parts['scheme'], $validSchemes)) {
- throw new \InvalidArgumentException("Invalid DSN. Supported schemes are " . implode(', ', $validSchemes));
- }
+ // Check the URI scheme
+ $validSchemes = ['redis', 'tcp'];
+ if (isset($parts['scheme']) && !in_array($parts['scheme'], $validSchemes)) {
+ throw new \InvalidArgumentException("Invalid DSN. Supported schemes are " . implode(', ', $validSchemes));
+ }
- // Allow simple 'hostname' format, which `parse_url` treats as a path, not host.
- if ( ! isset($parts['host']) && isset($parts['path'])) {
- $parts['host'] = $parts['path'];
- unset($parts['path']);
- }
+ // Allow simple 'hostname' format, which `parse_url` treats as a path, not host.
+ if (!isset($parts['host']) && isset($parts['path'])) {
+ $parts['host'] = $parts['path'];
+ unset($parts['path']);
+ }
- // Extract the port number as an integer
- $port = isset($parts['port']) ? intval($parts['port']) : self::DEFAULT_PORT;
+ // Extract the port number as an integer
+ $port = isset($parts['port']) ? intval($parts['port']) : self::DEFAULT_PORT;
- // Get the database from the 'path' part of the URI
- $database = false;
- if (isset($parts['path'])) {
- // Strip non-digit chars from path
- $database = intval(preg_replace('/[^0-9]/', '', $parts['path']));
- }
+ // Get the database from the 'path' part of the URI
+ $database = false;
+ if (isset($parts['path'])) {
+ // Strip non-digit chars from path
+ $database = intval(preg_replace('/[^0-9]/', '', $parts['path']));
+ }
- // Extract any 'user' and 'pass' values
- $user = isset($parts['user']) ? $parts['user'] : false;
- $pass = isset($parts['pass']) ? $parts['pass'] : false;
+ // Extract any 'user' and 'pass' values
+ $user = isset($parts['user']) ? $parts['user'] : false;
+ $pass = isset($parts['pass']) ? $parts['pass'] : false;
- // Convert the query string into an associative array
- $options = array();
- if (isset($parts['query'])) {
- // Parse the query string into an array
- parse_str($parts['query'], $options);
- }
+ // Convert the query string into an associative array
+ $options = [];
+ if (isset($parts['query'])) {
+ // Parse the query string into an array
+ parse_str($parts['query'], $options);
+ }
- return array(
- $parts['host'],
- $port,
- $database,
- $user,
- $pass,
- $options,
- );
- }
+ return [
+ $parts['host'],
+ $port,
+ $database,
+ $user,
+ $pass,
+ $options
+ ];
+ }
- /**
- * Magic method to handle all function requests and prefix key based
- * operations with the {self::$defaultNamespace} key prefix.
- *
- * @param string $name The name of the method called.
- * @param array $args Array of supplied arguments to the method.
- * @return mixed Return value from Resident::call() based on the command.
- */
- public function __call($name, $args)
- {
- if (in_array($name, $this->keyCommands)) {
- if (is_array($args[0])) {
- foreach ($args[0] AS $i => $v) {
- $args[0][$i] = self::$defaultNamespace . $v;
- }
- }
- else {
- $args[0] = self::$defaultNamespace . $args[0];
- }
- }
- try {
- return $this->driver->__call($name, $args);
- }
- catch (CredisException $e) {
- throw new Resque_RedisException('Error communicating with Redis: ' . $e->getMessage(), 0, $e);
- }
- }
+ /**
+ * Magic method to handle all function requests and prefix key based
+ * operations with the {self::$defaultNamespace} key prefix.
+ *
+ * @param string $name The name of the method called.
+ * @param array $args Array of supplied arguments to the method.
+ * @return mixed Return value from Resident::call() based on the command.
+ */
+ public function __call($name, $args)
+ {
+ if (in_array($name, $this->keyCommands)) {
+ if (is_array($args[0])) {
+ foreach ($args[0] AS $i => $v) {
+ $args[0][$i] = self::$defaultNamespace . $v;
+ }
+ } else {
+ $args[0] = self::$defaultNamespace . $args[0];
+ }
+ }
+ try {
+ return $this->driver->__call($name, $args);
+ } catch (CredisException $e) {
+ throw new Resque_RedisException('Error communicating with Redis: ' . $e->getMessage(), 0, $e);
+ }
+ }
- public static function getPrefix()
- {
- return self::$defaultNamespace;
- }
+ public static function getPrefix()
+ {
+ return self::$defaultNamespace;
+ }
- public static function removePrefix($string)
- {
- $prefix=self::getPrefix();
+ public static function removePrefix($string)
+ {
+ $prefix = self::getPrefix();
- if (substr($string, 0, strlen($prefix)) == $prefix) {
- $string = substr($string, strlen($prefix), strlen($string) );
- }
- return $string;
- }
+ if (substr($string, 0, strlen($prefix)) == $prefix) {
+ $string = substr($string, strlen($prefix), strlen($string));
+ }
+ return $string;
+ }
}
diff --git a/lib/Resque/RedisException.php b/lib/Resque/RedisException.php
index ca654a00..86e36dc1 100644
--- a/lib/Resque/RedisException.php
+++ b/lib/Resque/RedisException.php
@@ -1,12 +1,14 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_RedisException extends Resque_Exception
{
}
+
?>
\ No newline at end of file
diff --git a/lib/Resque/Stat.php b/lib/Resque/Stat.php
index bc00c636..e0af08e1 100644
--- a/lib/Resque/Stat.php
+++ b/lib/Resque/Stat.php
@@ -1,56 +1,57 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Stat
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Stat
{
- /**
- * Get the value of the supplied statistic counter for the specified statistic.
- *
- * @param string $stat The name of the statistic to get the stats for.
- * @return mixed Value of the statistic.
- */
- public static function get($stat)
- {
- return (int)Resque::redis()->get('stat:' . $stat);
- }
+ /**
+ * Get the value of the supplied statistic counter for the specified statistic.
+ *
+ * @param string $stat The name of the statistic to get the stats for.
+ * @return mixed Value of the statistic.
+ */
+ public static function get($stat)
+ {
+ return (int)Resque::redis()->get('stat:' . $stat);
+ }
- /**
- * Increment the value of the specified statistic by a certain amount (default is 1)
- *
- * @param string $stat The name of the statistic to increment.
- * @param int $by The amount to increment the statistic by.
- * @return boolean True if successful, false if not.
- */
- public static function incr($stat, $by = 1)
- {
- return (bool)Resque::redis()->incrby('stat:' . $stat, $by);
- }
+ /**
+ * Increment the value of the specified statistic by a certain amount (default is 1)
+ *
+ * @param string $stat The name of the statistic to increment.
+ * @param int $by The amount to increment the statistic by.
+ * @return boolean True if successful, false if not.
+ */
+ public static function incr($stat, $by = 1)
+ {
+ return (bool)Resque::redis()->incrby('stat:' . $stat, $by);
+ }
- /**
- * Decrement the value of the specified statistic by a certain amount (default is 1)
- *
- * @param string $stat The name of the statistic to decrement.
- * @param int $by The amount to decrement the statistic by.
- * @return boolean True if successful, false if not.
- */
- public static function decr($stat, $by = 1)
- {
- return (bool)Resque::redis()->decrby('stat:' . $stat, $by);
- }
+ /**
+ * Decrement the value of the specified statistic by a certain amount (default is 1)
+ *
+ * @param string $stat The name of the statistic to decrement.
+ * @param int $by The amount to decrement the statistic by.
+ * @return boolean True if successful, false if not.
+ */
+ public static function decr($stat, $by = 1)
+ {
+ return (bool)Resque::redis()->decrby('stat:' . $stat, $by);
+ }
- /**
- * 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);
- }
+ /**
+ * 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);
+ }
}
\ No newline at end of file
diff --git a/lib/Resque/Worker.php b/lib/Resque/Worker.php
index 04714c1c..dfd72003 100644
--- a/lib/Resque/Worker.php
+++ b/lib/Resque/Worker.php
@@ -5,51 +5,56 @@
* Resque worker that handles checking queues for jobs, fetching them
* off the queues, running them and handling the result.
*
- * @package Resque/Worker
- * @author Chris Boulton
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Worker
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Worker
{
- /**
- * @var LoggerInterface Logging object that impliments the PSR-3 LoggerInterface
- */
- public $logger;
-
- /**
- * @var array Array of all associated queues for this worker.
- */
- private $queues = array();
-
- /**
- * @var string The hostname of this worker.
- */
- private $hostname;
-
- /**
- * @var boolean True if on the next iteration, the worker should shutdown.
- */
- private $shutdown = false;
-
- /**
- * @var boolean True if this worker is paused.
- */
- private $paused = false;
-
- /**
- * @var string String identifying this worker.
- */
- private $id;
-
- /**
- * @var Resque_Job Current job, if any, being processed by this worker.
- */
- private $currentJob = null;
-
- /**
- * @var int Process ID of child worker processes.
- */
- private $child = null;
+ /**
+ * @var LoggerInterface Logging object that impliments the PSR-3 LoggerInterface
+ */
+ public $logger;
+
+ /**
+ * @var array Array of all associated queues for this worker.
+ */
+ private $queues = [];
+
+ /**
+ * @var string The hostname of this worker.
+ */
+ private $hostname;
+
+ /**
+ * @var boolean True if on the next iteration, the worker should shutdown.
+ */
+ private $shutdown = false;
+
+ /**
+ * @var boolean True if this worker is paused.
+ */
+ private $paused = false;
+
+ /**
+ * @var string String identifying this worker.
+ */
+ private $id;
+
+ /**
+ * @var Resque_Job Current job, if any, being processed by this worker.
+ */
+ private $currentJob = null;
+
+ /**
+ * @var boolean for display if this worker is working or not
+ */
+ private $working = false;
+
+ /**
+ * @var int Process ID of child worker processes.
+ */
+ private $child = null;
/**
* Instantiate a new worker, given a list of queues that it should be working
@@ -66,497 +71,514 @@ public function __construct($queues)
{
$this->logger = new Resque_Log();
- if(!is_array($queues)) {
- $queues = array($queues);
+ if (!is_array($queues)) {
+ $queues = [$queues];
}
$this->queues = $queues;
$this->hostname = php_uname('n');
- $this->id = $this->hostname . ':'.getmypid() . ':' . implode(',', $this->queues);
+ $this->id = $this->hostname . ':' . getmypid() . ':' . implode(',', $this->queues);
+ }
+
+ /**
+ * Return all workers known to Resque as instantiated instances.
+ * @return array
+ */
+ public static function all()
+ {
+ $workers = Resque::redis()->smembers('workers');
+ if (!is_array($workers)) {
+ $workers = [];
+ }
+
+ $instances = [];
+ foreach ($workers as $workerId) {
+ $instances[] = self::find($workerId);
+ }
+ return $instances;
+ }
+
+ /**
+ * Given a worker ID, check if it is registered/valid.
+ *
+ * @param string $workerId ID of the worker.
+ * @return boolean True if the worker exists, false if not.
+ */
+ public static function exists($workerId)
+ {
+ return (bool)Resque::redis()->sismember('workers', $workerId);
+ }
+
+ /**
+ * Given a worker ID, find it and return an instantiated worker class for it.
+ *
+ * @param string $workerId The ID of the worker.
+ * @return Resque_Worker Instance of the worker. False if the worker does not exist.
+ */
+ public static function find($workerId)
+ {
+ if (!self::exists($workerId) || false === strpos($workerId, ":")) {
+ return false;
+ }
+
+ list($hostname, $pid, $queues) = explode(':', $workerId, 3);
+ $queues = explode(',', $queues);
+ $worker = new self($queues);
+ $worker->setId($workerId);
+ return $worker;
+ }
+
+ /**
+ * Set the ID of this worker to a given ID string.
+ *
+ * @param string $workerId ID for the worker.
+ */
+ public function setId($workerId)
+ {
+ $this->id = $workerId;
+ }
+
+ /**
+ * The primary loop for a worker which when called on an instance starts
+ * the worker's life cycle.
+ *
+ * Queues are checked every $interval (seconds) for new jobs.
+ *
+ * @param int $interval How often to check for new jobs across the queues.
+ */
+ public function work($interval = Resque::DEFAULT_INTERVAL, $blocking = false)
+ {
+ $this->updateProcLine('Starting');
+ $this->startup();
+
+ while (true) {
+ if ($this->shutdown) {
+ break;
+ }
+
+ // Attempt to find and reserve a job
+ $job = false;
+ if (!$this->paused) {
+ if ($blocking === true) {
+ $this->logger->log(Psr\Log\LogLevel::INFO, 'Starting blocking with timeout of {interval}',
+ ['interval' => $interval]);
+ $this->updateProcLine('Waiting for ' . implode(',',
+ $this->queues) . ' with blocking timeout ' . $interval);
+ } else {
+ $this->updateProcLine('Waiting for ' . implode(',', $this->queues) . ' with interval ' . $interval);
+ }
+
+ $job = $this->reserve($blocking, $interval);
+ }
+
+ if (!$job) {
+ // For an interval of 0, break now - helps with unit testing etc
+ if ($interval == 0) {
+ break;
+ }
+
+ if ($blocking === false) {
+ // If no job was found, we sleep for $interval before continuing and checking again
+ $this->logger->log(Psr\Log\LogLevel::INFO, 'Sleeping for {interval}', ['interval' => $interval]);
+ if ($this->paused) {
+ $this->updateProcLine('Paused');
+ } else {
+ $this->updateProcLine('Waiting for ' . implode(',', $this->queues));
+ }
+
+ usleep($interval * 1000000);
+ }
+
+ continue;
+ }
+
+ $this->logger->log(Psr\Log\LogLevel::NOTICE, 'Starting work on {job}', ['job' => $job]);
+ Resque_Event::trigger('beforeFork', $job);
+ $this->workingOn($job);
+
+ $this->child = Resque::fork();
+
+ // Forked and we're the child. Run the job.
+ if ($this->child === 0 || $this->child === false) {
+ $status = 'Processing ' . $job->queue . ' since ' . date('d/m/Y h:i:s a');
+ $this->updateProcLine($status);
+ $this->logger->log(Psr\Log\LogLevel::INFO, $status);
+ $this->perform($job);
+ if ($this->child === 0) {
+ exit(0);
+ }
+ }
+
+ if ($this->child > 0) {
+ // Parent process, sit and wait
+ $status = 'Forked ' . $this->child . ' at ' . date('d/m/Y h:i:s a');
+ $this->updateProcLine($status);
+ $this->logger->log(Psr\Log\LogLevel::INFO, $status);
+
+ // Wait until the child process finishes before continuing
+ pcntl_wait($status);
+ $exitStatus = pcntl_wexitstatus($status);
+ if ($exitStatus !== 0) {
+ $job->fail(new Resque_Job_DirtyExitException(
+ 'Job exited with exit code ' . $exitStatus
+ ));
+ }
+ }
+
+ $this->child = null;
+ $this->doneWorking();
+ }
+
+ $this->unregisterWorker();
+ }
+
+ /**
+ * Process a single job.
+ *
+ * @param Resque_Job $job The job to be processed.
+ */
+ public function perform(Resque_Job $job)
+ {
+ try {
+ Resque_Event::trigger('afterFork', $job);
+ $job->perform();
+ } catch (Exception $e) {
+ $this->logger->log(Psr\Log\LogLevel::CRITICAL, '{job} has failed {stack}', ['job' => $job, 'stack' => $e]);
+ $job->fail($e);
+ return;
+ }
+
+ $job->updateStatus(Resque_Job_Status::STATUS_COMPLETE);
+ $this->logger->log(Psr\Log\LogLevel::NOTICE, '{job} has finished', ['job' => $job]);
+ }
+
+ /**
+ * @param bool $blocking
+ * @param int $timeout
+ * @return object|boolean Instance of Resque_Job if a job is found, false if not.
+ */
+ public function reserve($blocking = false, $timeout = null)
+ {
+ $queues = $this->queues();
+ if (!is_array($queues)) {
+ return false;
+ }
+
+ if ($blocking === true) {
+ $job = Resque_Job::reserveBlocking($queues, $timeout);
+ if ($job) {
+ $this->logger->log(Psr\Log\LogLevel::INFO, 'Found job on {queue}', ['queue' => $job->queue]);
+ return $job;
+ }
+ } else {
+ foreach ($queues as $queue) {
+ $this->logger->log(Psr\Log\LogLevel::INFO, 'Checking {queue} for jobs', ['queue' => $queue]);
+ $job = Resque_Job::reserve($queue);
+ if ($job) {
+ $this->logger->log(Psr\Log\LogLevel::INFO, 'Found job on {queue}', ['queue' => $job->queue]);
+ return $job;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Return an array containing all of the queues that this worker should use
+ * when searching for jobs.
+ *
+ * If * is found in the list of queues, every queue will be searched in
+ * alphabetic order. (@see $fetch)
+ *
+ * @param boolean $fetch If true, and the queue is set to *, will fetch
+ * all queue names from redis.
+ * @return array Array of associated queues.
+ */
+ public function queues($fetch = true)
+ {
+ if (!in_array('*', $this->queues) || $fetch == false) {
+ return $this->queues;
+ }
+
+ $queues = Resque::queues();
+ sort($queues);
+ return $queues;
+ }
+
+ /**
+ * Perform necessary actions to start a worker.
+ */
+ private function startup()
+ {
+ $this->registerSigHandlers();
+ $this->pruneDeadWorkers();
+ Resque_Event::trigger('beforeFirstFork', $this);
+ $this->registerWorker();
+ }
+
+ /**
+ * On supported systems (with the PECL proctitle module installed), update
+ * the name of the currently running process to indicate the current state
+ * of a worker.
+ *
+ * @param string $status The updated process title.
+ */
+ private function updateProcLine($status)
+ {
+ $processTitle = 'resque-worker-' . $this . ' ' . Resque::VERSION . ': ' . $status;
+ if (function_exists('cli_set_process_title') && PHP_OS !== 'Darwin') {
+ cli_set_process_title($processTitle);
+ } else {
+ if (function_exists('setproctitle')) {
+ setproctitle($processTitle);
+ }
+ }
+ }
+
+ /**
+ * Register signal handlers that a worker should respond to.
+ *
+ * TERM: Shutdown immediately and stop processing jobs.
+ * INT: Shutdown immediately and stop processing jobs.
+ * QUIT: Shutdown after the current job finishes processing.
+ * USR1: Kill the forked child immediately and continue processing jobs.
+ */
+ private function registerSigHandlers()
+ {
+ if (!function_exists('pcntl_signal')) {
+ return;
+ }
+
+ pcntl_signal(SIGTERM, [$this, 'shutDownNow']);
+ pcntl_signal(SIGINT, [$this, 'shutDownNow']);
+ pcntl_signal(SIGQUIT, [$this, 'shutdown']);
+ pcntl_signal(SIGUSR1, [$this, 'killChild']);
+ pcntl_signal(SIGUSR2, [$this, 'pauseProcessing']);
+ pcntl_signal(SIGCONT, [$this, 'unPauseProcessing']);
+ $this->logger->log(Psr\Log\LogLevel::DEBUG, 'Registered signals');
+ }
+
+ /**
+ * Signal handler callback for USR2, pauses processing of new jobs.
+ */
+ public function pauseProcessing()
+ {
+ $this->logger->log(Psr\Log\LogLevel::NOTICE, 'USR2 received; pausing job processing');
+ $this->paused = true;
+ }
+
+ /**
+ * Signal handler callback for CONT, resumes worker allowing it to pick
+ * up new jobs.
+ */
+ public function unPauseProcessing()
+ {
+ $this->logger->log(Psr\Log\LogLevel::NOTICE, 'CONT received; resuming job processing');
+ $this->paused = false;
}
- /**
- * Return all workers known to Resque as instantiated instances.
- * @return array
- */
- public static function all()
- {
- $workers = Resque::redis()->smembers('workers');
- if(!is_array($workers)) {
- $workers = array();
- }
-
- $instances = array();
- foreach($workers as $workerId) {
- $instances[] = self::find($workerId);
- }
- return $instances;
- }
-
- /**
- * Given a worker ID, check if it is registered/valid.
- *
- * @param string $workerId ID of the worker.
- * @return boolean True if the worker exists, false if not.
- */
- public static function exists($workerId)
- {
- return (bool)Resque::redis()->sismember('workers', $workerId);
- }
-
- /**
- * Given a worker ID, find it and return an instantiated worker class for it.
- *
- * @param string $workerId The ID of the worker.
- * @return Resque_Worker Instance of the worker. False if the worker does not exist.
- */
- public static function find($workerId)
- {
- if(!self::exists($workerId) || false === strpos($workerId, ":")) {
- return false;
- }
-
- list($hostname, $pid, $queues) = explode(':', $workerId, 3);
- $queues = explode(',', $queues);
- $worker = new self($queues);
- $worker->setId($workerId);
- return $worker;
- }
-
- /**
- * Set the ID of this worker to a given ID string.
- *
- * @param string $workerId ID for the worker.
- */
- public function setId($workerId)
- {
- $this->id = $workerId;
- }
-
- /**
- * The primary loop for a worker which when called on an instance starts
- * the worker's life cycle.
- *
- * Queues are checked every $interval (seconds) for new jobs.
- *
- * @param int $interval How often to check for new jobs across the queues.
- */
- public function work($interval = Resque::DEFAULT_INTERVAL, $blocking = false)
- {
- $this->updateProcLine('Starting');
- $this->startup();
-
- while(true) {
- if($this->shutdown) {
- break;
- }
-
- // Attempt to find and reserve a job
- $job = false;
- if(!$this->paused) {
- if($blocking === true) {
- $this->logger->log(Psr\Log\LogLevel::INFO, 'Starting blocking with timeout of {interval}', array('interval' => $interval));
- $this->updateProcLine('Waiting for ' . implode(',', $this->queues) . ' with blocking timeout ' . $interval);
- } else {
- $this->updateProcLine('Waiting for ' . implode(',', $this->queues) . ' with interval ' . $interval);
- }
-
- $job = $this->reserve($blocking, $interval);
- }
-
- if(!$job) {
- // For an interval of 0, break now - helps with unit testing etc
- if($interval == 0) {
- break;
- }
-
- if($blocking === false)
- {
- // If no job was found, we sleep for $interval before continuing and checking again
- $this->logger->log(Psr\Log\LogLevel::INFO, 'Sleeping for {interval}', array('interval' => $interval));
- if($this->paused) {
- $this->updateProcLine('Paused');
- }
- else {
- $this->updateProcLine('Waiting for ' . implode(',', $this->queues));
- }
-
- usleep($interval * 1000000);
- }
-
- continue;
- }
-
- $this->logger->log(Psr\Log\LogLevel::NOTICE, 'Starting work on {job}', array('job' => $job));
- Resque_Event::trigger('beforeFork', $job);
- $this->workingOn($job);
-
- $this->child = Resque::fork();
-
- // Forked and we're the child. Run the job.
- if ($this->child === 0 || $this->child === false) {
- $status = 'Processing ' . $job->queue . ' since ' . strftime('%F %T');
- $this->updateProcLine($status);
- $this->logger->log(Psr\Log\LogLevel::INFO, $status);
- $this->perform($job);
- if ($this->child === 0) {
- exit(0);
- }
- }
-
- if($this->child > 0) {
- // Parent process, sit and wait
- $status = 'Forked ' . $this->child . ' at ' . strftime('%F %T');
- $this->updateProcLine($status);
- $this->logger->log(Psr\Log\LogLevel::INFO, $status);
-
- // Wait until the child process finishes before continuing
- pcntl_wait($status);
- $exitStatus = pcntl_wexitstatus($status);
- if($exitStatus !== 0) {
- $job->fail(new Resque_Job_DirtyExitException(
- 'Job exited with exit code ' . $exitStatus
- ));
- }
- }
-
- $this->child = null;
- $this->doneWorking();
- }
-
- $this->unregisterWorker();
- }
-
- /**
- * Process a single job.
- *
- * @param Resque_Job $job The job to be processed.
- */
- public function perform(Resque_Job $job)
- {
- try {
- Resque_Event::trigger('afterFork', $job);
- $job->perform();
- }
- catch(Exception $e) {
- $this->logger->log(Psr\Log\LogLevel::CRITICAL, '{job} has failed {stack}', array('job' => $job, 'stack' => $e));
- $job->fail($e);
- return;
- }
-
- $job->updateStatus(Resque_Job_Status::STATUS_COMPLETE);
- $this->logger->log(Psr\Log\LogLevel::NOTICE, '{job} has finished', array('job' => $job));
- }
-
- /**
- * @param bool $blocking
- * @param int $timeout
- * @return object|boolean Instance of Resque_Job if a job is found, false if not.
- */
- public function reserve($blocking = false, $timeout = null)
- {
- $queues = $this->queues();
- if(!is_array($queues)) {
- return;
- }
-
- if($blocking === true) {
- $job = Resque_Job::reserveBlocking($queues, $timeout);
- if($job) {
- $this->logger->log(Psr\Log\LogLevel::INFO, 'Found job on {queue}', array('queue' => $job->queue));
- return $job;
- }
- } else {
- foreach($queues as $queue) {
- $this->logger->log(Psr\Log\LogLevel::INFO, 'Checking {queue} for jobs', array('queue' => $queue));
- $job = Resque_Job::reserve($queue);
- if($job) {
- $this->logger->log(Psr\Log\LogLevel::INFO, 'Found job on {queue}', array('queue' => $job->queue));
- return $job;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Return an array containing all of the queues that this worker should use
- * when searching for jobs.
- *
- * If * is found in the list of queues, every queue will be searched in
- * alphabetic order. (@see $fetch)
- *
- * @param boolean $fetch If true, and the queue is set to *, will fetch
- * all queue names from redis.
- * @return array Array of associated queues.
- */
- public function queues($fetch = true)
- {
- if(!in_array('*', $this->queues) || $fetch == false) {
- return $this->queues;
- }
-
- $queues = Resque::queues();
- sort($queues);
- return $queues;
- }
-
- /**
- * Perform necessary actions to start a worker.
- */
- private function startup()
- {
- $this->registerSigHandlers();
- $this->pruneDeadWorkers();
- Resque_Event::trigger('beforeFirstFork', $this);
- $this->registerWorker();
- }
-
- /**
- * On supported systems (with the PECL proctitle module installed), update
- * the name of the currently running process to indicate the current state
- * of a worker.
- *
- * @param string $status The updated process title.
- */
- private function updateProcLine($status)
- {
- $processTitle = 'resque-' . Resque::VERSION . ': ' . $status;
- if(function_exists('cli_set_process_title') && PHP_OS !== 'Darwin') {
- cli_set_process_title($processTitle);
- }
- else if(function_exists('setproctitle')) {
- setproctitle($processTitle);
- }
- }
-
- /**
- * Register signal handlers that a worker should respond to.
- *
- * TERM: Shutdown immediately and stop processing jobs.
- * INT: Shutdown immediately and stop processing jobs.
- * QUIT: Shutdown after the current job finishes processing.
- * USR1: Kill the forked child immediately and continue processing jobs.
- */
- private function registerSigHandlers()
- {
- if(!function_exists('pcntl_signal')) {
- return;
- }
-
- pcntl_signal(SIGTERM, array($this, 'shutDownNow'));
- pcntl_signal(SIGINT, array($this, 'shutDownNow'));
- pcntl_signal(SIGQUIT, array($this, 'shutdown'));
- pcntl_signal(SIGUSR1, array($this, 'killChild'));
- pcntl_signal(SIGUSR2, array($this, 'pauseProcessing'));
- pcntl_signal(SIGCONT, array($this, 'unPauseProcessing'));
- $this->logger->log(Psr\Log\LogLevel::DEBUG, 'Registered signals');
- }
-
- /**
- * Signal handler callback for USR2, pauses processing of new jobs.
- */
- public function pauseProcessing()
- {
- $this->logger->log(Psr\Log\LogLevel::NOTICE, 'USR2 received; pausing job processing');
- $this->paused = true;
- }
-
- /**
- * Signal handler callback for CONT, resumes worker allowing it to pick
- * up new jobs.
- */
- public function unPauseProcessing()
- {
- $this->logger->log(Psr\Log\LogLevel::NOTICE, 'CONT received; resuming job processing');
- $this->paused = false;
- }
-
- /**
- * Schedule a worker for shutdown. Will finish processing the current job
- * and when the timeout interval is reached, the worker will shut down.
- */
- public function shutdown()
- {
- $this->shutdown = true;
- $this->logger->log(Psr\Log\LogLevel::NOTICE, 'Shutting down');
- }
-
- /**
- * Force an immediate shutdown of the worker, killing any child jobs
- * currently running.
- */
- public function shutdownNow()
- {
- $this->shutdown();
- $this->killChild();
- }
-
- /**
- * Kill a forked child job immediately. The job it is processing will not
- * be completed.
- */
- public function killChild()
- {
- if(!$this->child) {
- $this->logger->log(Psr\Log\LogLevel::DEBUG, 'No child to kill.');
- return;
- }
-
- $this->logger->log(Psr\Log\LogLevel::INFO, 'Killing child at {child}', array('child' => $this->child));
- if(exec('ps -o pid,state -p ' . $this->child, $output, $returnCode) && $returnCode != 1) {
- $this->logger->log(Psr\Log\LogLevel::DEBUG, 'Child {child} found, killing.', array('child' => $this->child));
- posix_kill($this->child, SIGKILL);
- $this->child = null;
- }
- else {
- $this->logger->log(Psr\Log\LogLevel::INFO, 'Child {child} not found, restarting.', array('child' => $this->child));
- $this->shutdown();
- }
- }
-
- /**
- * 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 Resque workers did not die gracefully
- * and therefore leave state information in Redis.
- */
- public function pruneDeadWorkers()
- {
- $workerPids = $this->workerPids();
- $workers = self::all();
- foreach($workers as $worker) {
- if (is_object($worker)) {
- list($host, $pid, $queues) = explode(':', (string)$worker, 3);
- if($host != $this->hostname || in_array($pid, $workerPids) || $pid == getmypid()) {
- continue;
- }
- $this->logger->log(Psr\Log\LogLevel::INFO, 'Pruning dead worker: {worker}', array('worker' => (string)$worker));
- $worker->unregisterWorker();
- }
- }
- }
-
- /**
- * Return an array of process IDs for all of the Resque workers currently
- * running on this machine.
- *
- * @return array Array of Resque worker process IDs.
- */
- public function workerPids()
- {
- $pids = array();
- exec('ps -A -o pid,command | grep [r]esque', $cmdOutput);
- foreach($cmdOutput as $line) {
- list($pids[],) = explode(' ', trim($line), 2);
- }
- return $pids;
- }
-
- /**
- * Register this worker in Redis.
- */
- public function registerWorker()
- {
- Resque::redis()->sadd('workers', (string)$this);
- Resque::redis()->set('worker:' . (string)$this . ':started', strftime('%a %b %d %H:%M:%S %Z %Y'));
- }
-
- /**
- * Unregister this worker in Redis. (shutdown etc)
- */
- public function unregisterWorker()
- {
- if(is_object($this->currentJob)) {
- $this->currentJob->fail(new Resque_Job_DirtyExitException);
- }
-
- $id = (string)$this;
- Resque::redis()->srem('workers', $id);
- Resque::redis()->del('worker:' . $id);
- Resque::redis()->del('worker:' . $id . ':started');
- Resque_Stat::clear('processed:' . $id);
- Resque_Stat::clear('failed:' . $id);
- }
-
- /**
- * Tell Redis which job we're currently working on.
- *
- * @param object $job Resque_Job instance containing the job we're working on.
- */
- public function workingOn(Resque_Job $job)
- {
- $job->worker = $this;
- $this->currentJob = $job;
- $job->updateStatus(Resque_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);
- }
-
- /**
- * Notify Redis that we've finished working on a job, clearing the working
- * state and incrementing the job stats.
- */
- public function doneWorking()
- {
- $this->currentJob = null;
- Resque_Stat::incr('processed');
- Resque_Stat::incr('processed:' . (string)$this);
- Resque::redis()->del('worker:' . (string)$this);
- }
-
- /**
- * Generate a string representation of this worker.
- *
- * @return string String identifier for this worker instance.
- */
- public function __toString()
- {
- return $this->id;
- }
-
- /**
- * 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);
- }
- }
-
- /**
- * Get a statistic belonging to this worker.
- *
- * @param string $stat Statistic to fetch.
- * @return int Statistic value.
- */
- public function getStat($stat)
- {
- return Resque_Stat::get($stat . ':' . $this);
- }
-
- /**
- * Inject the logging object into the worker
- *
- * @param Psr\Log\LoggerInterface $logger
- */
- public function setLogger(Psr\Log\LoggerInterface $logger)
- {
- $this->logger = $logger;
- }
+ /**
+ * Schedule a worker for shutdown. Will finish processing the current job
+ * and when the timeout interval is reached, the worker will shut down.
+ */
+ public function shutdown()
+ {
+ $this->shutdown = true;
+ $this->logger->log(Psr\Log\LogLevel::NOTICE, 'Shutting down');
+ }
+
+ /**
+ * Force an immediate shutdown of the worker, killing any child jobs
+ * currently running.
+ */
+ public function shutdownNow()
+ {
+ $this->shutdown();
+ $this->killChild();
+ }
+
+ /**
+ * Kill a forked child job immediately. The job it is processing will not
+ * be completed.
+ */
+ public function killChild()
+ {
+ if (!$this->child) {
+ $this->logger->log(Psr\Log\LogLevel::DEBUG, 'No child to kill.');
+ return;
+ }
+
+ $this->logger->log(Psr\Log\LogLevel::INFO, 'Killing child at {child}', ['child' => $this->child]);
+ if (exec('ps -o pid,state -p ' . $this->child, $output, $returnCode) && $returnCode != 1) {
+ $this->logger->log(Psr\Log\LogLevel::DEBUG, 'Child {child} found, killing.', ['child' => $this->child]);
+ posix_kill($this->child, SIGKILL);
+ $this->child = null;
+ } else {
+ $this->logger->log(Psr\Log\LogLevel::INFO, 'Child {child} not found, restarting.',
+ ['child' => $this->child]);
+ $this->shutdown();
+ }
+ }
+
+ /**
+ * 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 Resque workers did not die gracefully
+ * and therefore leave state information in Redis.
+ */
+ public function pruneDeadWorkers()
+ {
+ $workerPids = self::workerPids();
+ $workers = self::all();
+ foreach ($workers as $worker) {
+ if (is_object($worker)) {
+ list($host, $pid, $queues) = explode(':', (string)$worker, 3);
+ if ($host != $this->hostname || in_array($pid, $workerPids) || $pid == getmypid()) {
+ continue;
+ }
+ $this->logger->log(Psr\Log\LogLevel::INFO, 'Pruning dead worker: {worker}',
+ ['worker' => (string)$worker]);
+ $worker->unregisterWorker();
+ }
+ }
+ }
+
+ /**
+ * Return an array of process IDs for all of the Resque workers currently
+ * running on this machine.
+ *
+ * @return array Array of Resque worker process IDs.
+ */
+ public static function workerPids()
+ {
+ $pids = [];
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ exec('tasklist /v /fi "PID gt 1" /fo csv', $cmdOutput);
+ foreach ($cmdOutput as $line) {
+ $a = explode(',', $line);
+ list(, $pids[],) = str_replace('"', '', explode(',', trim($line), 3));
+ }
+ } else {
+ exec('ps -A -o pid,command | grep [r]esque', $cmdOutput);
+ foreach ($cmdOutput as $line) {
+ list($pids[],) = explode(' ', trim($line), 2);
+ }
+ }
+ return $pids;
+ }
+
+ /**
+ * Register this worker in Redis.
+ */
+ public function registerWorker()
+ {
+ Resque::redis()->sadd('workers', (string)$this);
+ Resque::redis()->set('worker:' . (string)$this . ':started', strftime('%a %b %d %H:%M:%S %Z %Y'));
+ }
+
+ /**
+ * Unregister this worker in Redis. (shutdown etc)
+ */
+ public function unregisterWorker()
+ {
+ if (is_object($this->currentJob)) {
+ $this->currentJob->fail(new Resque_Job_DirtyExitException);
+ }
+
+ $id = (string)$this;
+ Resque::redis()->srem('workers', $id);
+ Resque::redis()->del('worker:' . $id);
+ Resque::redis()->del('worker:' . $id . ':started');
+ Resque_Stat::clear('processed:' . $id);
+ Resque_Stat::clear('failed:' . $id);
+ }
+
+ /**
+ * Tell Redis which job we're currently working on.
+ *
+ * @param object $job Resque_Job instance containing the job we're working on.
+ */
+ public function workingOn(Resque_Job $job)
+ {
+ $job->worker = $this;
+ $this->currentJob = $job;
+ $this->working = true;
+ $job->updateStatus(Resque_Job_Status::STATUS_RUNNING);
+ $data = json_encode([
+ 'queue' => $job->queue,
+ 'run_at' => strftime('%a %b %d %H:%M:%S %Z %Y'),
+ 'payload' => $job->payload
+ ]);
+ Resque::redis()->set('worker:' . $job->worker, $data);
+ }
+
+ /**
+ * @return boolean get for the private attribute
+ */
+ public function getWorking(){
+ return $this->working;
+ }
+
+ /**
+ * Notify Redis that we've finished working on a job, clearing the working
+ * state and incrementing the job stats.
+ */
+ public function doneWorking()
+ {
+ $this->currentJob = null;
+ $this->working = false;
+ Resque_Stat::incr('processed');
+ Resque_Stat::incr('processed:' . (string)$this);
+ Resque::redis()->del('worker:' . (string)$this);
+ }
+
+ /**
+ * Generate a string representation of this worker.
+ *
+ * @return string String identifier for this worker instance.
+ */
+ public function __toString()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Return an object describing the job this worker is currently working on.
+ *
+ * @return object|array Object with details of current job.
+ */
+ public function job()
+ {
+ $job = Resque::redis()->get('worker:' . $this);
+ if (!$job) {
+ return [];
+ } else {
+ return json_decode($job, true);
+ }
+ }
+
+ /**
+ * Get a statistic belonging to this worker.
+ *
+ * @param string $stat Statistic to fetch.
+ * @return int Statistic value.
+ */
+ public function getStat($stat)
+ {
+ return Resque_Stat::get($stat . ':' . $this);
+ }
+
+ /**
+ * Inject the logging object into the worker
+ *
+ * @param Psr\Log\LoggerInterface $logger
+ */
+ public function setLogger(Psr\Log\LoggerInterface $logger)
+ {
+ $this->logger = $logger;
+ }
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 61d2d7b3..8b7667fc 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,24 +1,24 @@
-
-
- ./test/Resque/
-
-
+
+
+ ./test/Resque/
+
+
-
-
- ./lib/Resque/
-
-
+
+
+ ./lib/Resque/
+
+
\ No newline at end of file
diff --git a/test/Resque/Tests/EventTest.php b/test/Resque/Tests/EventTest.php
index 6e102cf4..060755ef 100644
--- a/test/Resque/Tests/EventTest.php
+++ b/test/Resque/Tests/EventTest.php
@@ -1,199 +1,201 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Tests
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Tests_EventTest extends Resque_Tests_TestCase
{
- private $callbacksHit = array();
-
- public function setUp()
- {
- Test_Job::$called = false;
-
- // Register a worker to test with
- $this->worker = new Resque_Worker('jobs');
- $this->worker->setLogger(new Resque_Log());
- $this->worker->registerWorker();
- }
-
- public function tearDown()
- {
- Resque_Event::clearListeners();
- $this->callbacksHit = array();
- }
-
- public function getEventTestJob()
- {
- $payload = array(
- 'class' => 'Test_Job',
- 'args' => array(
- array('somevar'),
- ),
- );
- $job = new Resque_Job('jobs', $payload);
- $job->worker = $this->worker;
- return $job;
- }
-
- public function eventCallbackProvider()
- {
- return array(
- array('beforePerform', 'beforePerformEventCallback'),
- array('afterPerform', 'afterPerformEventCallback'),
- array('afterFork', 'afterForkEventCallback'),
- );
- }
-
- /**
- * @dataProvider eventCallbackProvider
- */
- public function testEventCallbacksFire($event, $callback)
- {
- Resque_Event::listen($event, array($this, $callback));
-
- $job = $this->getEventTestJob();
- $this->worker->perform($job);
- $this->worker->work(0);
-
- $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback .') was not called');
- }
-
- public function testBeforeForkEventCallbackFires()
- {
- $event = 'beforeFork';
- $callback = 'beforeForkEventCallback';
-
- Resque_Event::listen($event, array($this, $callback));
- Resque::enqueue('jobs', 'Test_Job', array(
- 'somevar'
- ));
- $job = $this->getEventTestJob();
- $this->worker->work(0);
- $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback .') was not called');
- }
-
- public function testBeforeEnqueueEventCallbackFires()
- {
- $event = 'beforeEnqueue';
- $callback = 'beforeEnqueueEventCallback';
-
- Resque_Event::listen($event, array($this, $callback));
- Resque::enqueue('jobs', 'Test_Job', array(
- 'somevar'
- ));
- $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback .') was not called');
- }
-
- public function testBeforePerformEventCanStopWork()
- {
- $callback = 'beforePerformEventDontPerformCallback';
- Resque_Event::listen('beforePerform', array($this, $callback));
-
- $job = $this->getEventTestJob();
-
- $this->assertFalse($job->perform());
- $this->assertContains($callback, $this->callbacksHit, $callback . ' callback was not called');
- $this->assertFalse(Test_Job::$called, 'Job was still performed though Resque_Job_DontPerform was thrown');
- }
-
- public function testBeforeEnqueueEventStopsJobCreation()
- {
- $callback = 'beforeEnqueueEventDontCreateCallback';
- Resque_Event::listen('beforeEnqueue', array($this, $callback));
- Resque_Event::listen('afterEnqueue', array($this, 'afterEnqueueEventCallback'));
-
- $result = Resque::enqueue('test_job', 'TestClass');
- $this->assertContains($callback, $this->callbacksHit, $callback . ' callback was not called');
- $this->assertNotContains('afterEnqueueEventCallback', $this->callbacksHit, 'afterEnqueue was still called, even though it should not have been');
- $this->assertFalse($result);
- }
-
- public function testAfterEnqueueEventCallbackFires()
- {
- $callback = 'afterEnqueueEventCallback';
- $event = 'afterEnqueue';
-
- Resque_Event::listen($event, array($this, $callback));
- Resque::enqueue('jobs', 'Test_Job', array(
- 'somevar'
- ));
- $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback .') was not called');
- }
-
- public function testStopListeningRemovesListener()
- {
- $callback = 'beforePerformEventCallback';
- $event = 'beforePerform';
-
- Resque_Event::listen($event, array($this, $callback));
- Resque_Event::stopListening($event, array($this, $callback));
-
- $job = $this->getEventTestJob();
- $this->worker->perform($job);
- $this->worker->work(0);
-
- $this->assertNotContains($callback, $this->callbacksHit,
- $event . ' callback (' . $callback .') was called though Resque_Event::stopListening was called'
- );
- }
-
- public function beforePerformEventDontPerformCallback($instance)
- {
- $this->callbacksHit[] = __FUNCTION__;
- throw new Resque_Job_DontPerform;
- }
-
- public function beforeEnqueueEventDontCreateCallback($queue, $class, $args, $track = false)
- {
- $this->callbacksHit[] = __FUNCTION__;
- throw new Resque_Job_DontCreate;
- }
-
- public function assertValidEventCallback($function, $job)
- {
- $this->callbacksHit[] = $function;
- if (!$job instanceof Resque_Job) {
- $this->fail('Callback job argument is not an instance of Resque_Job');
- }
- $args = $job->getArguments();
- $this->assertEquals($args[0], 'somevar');
- }
-
- public function afterEnqueueEventCallback($class, $args)
- {
- $this->callbacksHit[] = __FUNCTION__;
- $this->assertEquals('Test_Job', $class);
- $this->assertEquals(array(
- 'somevar',
- ), $args);
- }
-
- public function beforeEnqueueEventCallback($job)
- {
- $this->callbacksHit[] = __FUNCTION__;
- }
-
- public function beforePerformEventCallback($job)
- {
- $this->assertValidEventCallback(__FUNCTION__, $job);
- }
-
- public function afterPerformEventCallback($job)
- {
- $this->assertValidEventCallback(__FUNCTION__, $job);
- }
-
- public function beforeForkEventCallback($job)
- {
- $this->assertValidEventCallback(__FUNCTION__, $job);
- }
-
- public function afterForkEventCallback($job)
- {
- $this->assertValidEventCallback(__FUNCTION__, $job);
- }
+ private $callbacksHit = [];
+
+ public function setUp()
+ {
+ Test_Job::$called = false;
+
+ // Register a worker to test with
+ $this->worker = new Resque_Worker('jobs');
+ $this->worker->setLogger(new Resque_Log());
+ $this->worker->registerWorker();
+ }
+
+ public function tearDown()
+ {
+ Resque_Event::clearListeners();
+ $this->callbacksHit = [];
+ }
+
+ public function getEventTestJob()
+ {
+ $payload = [
+ 'class' => 'Test_Job',
+ 'args' => [
+ ['somevar']
+ ],
+ ];
+ $job = new Resque_Job('jobs', $payload);
+ $job->worker = $this->worker;
+ return $job;
+ }
+
+ public function eventCallbackProvider()
+ {
+ return [
+ ['beforePerform', 'beforePerformEventCallback'],
+ ['afterPerform', 'afterPerformEventCallback'],
+ ['afterFork', 'afterForkEventCallback']
+ ];
+ }
+
+ /**
+ * @dataProvider eventCallbackProvider
+ */
+ public function testEventCallbacksFire($event, $callback)
+ {
+ Resque_Event::listen($event, [$this, $callback]);
+
+ $job = $this->getEventTestJob();
+ $this->worker->perform($job);
+ $this->worker->work(0);
+
+ $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called');
+ }
+
+ public function testBeforeForkEventCallbackFires()
+ {
+ $event = 'beforeFork';
+ $callback = 'beforeForkEventCallback';
+
+ Resque_Event::listen($event, [$this, $callback]);
+ Resque::enqueue('jobs', 'Test_Job', [
+ 'somevar'
+ ]);
+ $job = $this->getEventTestJob();
+ $this->worker->work(0);
+ $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called');
+ }
+
+ public function testBeforeEnqueueEventCallbackFires()
+ {
+ $event = 'beforeEnqueue';
+ $callback = 'beforeEnqueueEventCallback';
+
+ Resque_Event::listen($event, [$this, $callback]);
+ Resque::enqueue('jobs', 'Test_Job', [
+ 'somevar'
+ ]);
+ $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called');
+ }
+
+ public function testBeforePerformEventCanStopWork()
+ {
+ $callback = 'beforePerformEventDontPerformCallback';
+ Resque_Event::listen('beforePerform', [$this, $callback]);
+
+ $job = $this->getEventTestJob();
+
+ $this->assertFalse($job->perform());
+ $this->assertContains($callback, $this->callbacksHit, $callback . ' callback was not called');
+ $this->assertFalse(Test_Job::$called, 'Job was still performed though Resque_Job_DontPerform was thrown');
+ }
+
+ public function testBeforeEnqueueEventStopsJobCreation()
+ {
+ $callback = 'beforeEnqueueEventDontCreateCallback';
+ Resque_Event::listen('beforeEnqueue', [$this, $callback]);
+ Resque_Event::listen('afterEnqueue', [$this, 'afterEnqueueEventCallback']);
+
+ $result = Resque::enqueue('test_job', 'TestClass');
+ $this->assertContains($callback, $this->callbacksHit, $callback . ' callback was not called');
+ $this->assertNotContains('afterEnqueueEventCallback', $this->callbacksHit,
+ 'afterEnqueue was still called, even though it should not have been');
+ $this->assertFalse($result);
+ }
+
+ public function testAfterEnqueueEventCallbackFires()
+ {
+ $callback = 'afterEnqueueEventCallback';
+ $event = 'afterEnqueue';
+
+ Resque_Event::listen($event, [$this, $callback]);
+ Resque::enqueue('jobs', 'Test_Job', [
+ 'somevar'
+ ]);
+ $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called');
+ }
+
+ public function testStopListeningRemovesListener()
+ {
+ $callback = 'beforePerformEventCallback';
+ $event = 'beforePerform';
+
+ Resque_Event::listen($event, [$this, $callback]);
+ Resque_Event::stopListening($event, [$this, $callback]);
+
+ $job = $this->getEventTestJob();
+ $this->worker->perform($job);
+ $this->worker->work(0);
+
+ $this->assertNotContains($callback, $this->callbacksHit,
+ $event . ' callback (' . $callback . ') was called though Resque_Event::stopListening was called'
+ );
+ }
+
+ public function beforePerformEventDontPerformCallback($instance)
+ {
+ $this->callbacksHit[] = __FUNCTION__;
+ throw new Resque_Job_DontPerform;
+ }
+
+ public function beforeEnqueueEventDontCreateCallback($queue, $class, $args, $track = false)
+ {
+ $this->callbacksHit[] = __FUNCTION__;
+ throw new Resque_Job_DontCreate;
+ }
+
+ public function assertValidEventCallback($function, $job)
+ {
+ $this->callbacksHit[] = $function;
+ if (!$job instanceof Resque_Job) {
+ $this->fail('Callback job argument is not an instance of Resque_Job');
+ }
+ $args = $job->getArguments();
+ $this->assertEquals($args[0], 'somevar');
+ }
+
+ public function afterEnqueueEventCallback($class, $args)
+ {
+ $this->callbacksHit[] = __FUNCTION__;
+ $this->assertEquals('Test_Job', $class);
+ $this->assertEquals([
+ 'somevar'
+ ], $args);
+ }
+
+ public function beforeEnqueueEventCallback($job)
+ {
+ $this->callbacksHit[] = __FUNCTION__;
+ }
+
+ public function beforePerformEventCallback($job)
+ {
+ $this->assertValidEventCallback(__FUNCTION__, $job);
+ }
+
+ public function afterPerformEventCallback($job)
+ {
+ $this->assertValidEventCallback(__FUNCTION__, $job);
+ }
+
+ public function beforeForkEventCallback($job)
+ {
+ $this->assertValidEventCallback(__FUNCTION__, $job);
+ }
+
+ public function afterForkEventCallback($job)
+ {
+ $this->assertValidEventCallback(__FUNCTION__, $job);
+ }
}
diff --git a/test/Resque/Tests/JobStatusTest.php b/test/Resque/Tests/JobStatusTest.php
index d751c37f..79e5c6cd 100644
--- a/test/Resque/Tests/JobStatusTest.php
+++ b/test/Resque/Tests/JobStatusTest.php
@@ -1,10 +1,11 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Tests
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Tests_JobStatusTest extends Resque_Tests_TestCase
{
@@ -13,94 +14,94 @@ class Resque_Tests_JobStatusTest extends Resque_Tests_TestCase
*/
protected $worker;
- public function setUp()
- {
- parent::setUp();
-
- // Register a worker to test with
- $this->worker = new Resque_Worker('jobs');
- $this->worker->setLogger(new Resque_Log());
- }
-
- public function testJobStatusCanBeTracked()
- {
- $token = Resque::enqueue('jobs', 'Test_Job', null, true);
- $status = new Resque_Job_Status($token);
- $this->assertTrue($status->isTracking());
- }
-
- public function testJobStatusIsReturnedViaJobInstance()
- {
- $token = Resque::enqueue('jobs', 'Test_Job', null, true);
- $job = Resque_Job::reserve('jobs');
- $this->assertEquals(Resque_Job_Status::STATUS_WAITING, $job->getStatus());
- }
-
- public function testQueuedJobReturnsQueuedStatus()
- {
- $token = Resque::enqueue('jobs', 'Test_Job', null, true);
- $status = new Resque_Job_Status($token);
- $this->assertEquals(Resque_Job_Status::STATUS_WAITING, $status->get());
- }
-
- public function testRunningJobReturnsRunningStatus()
- {
- $token = Resque::enqueue('jobs', 'Failing_Job', null, true);
- $job = $this->worker->reserve();
- $this->worker->workingOn($job);
- $status = new Resque_Job_Status($token);
- $this->assertEquals(Resque_Job_Status::STATUS_RUNNING, $status->get());
- }
-
- public function testFailedJobReturnsFailedStatus()
- {
- $token = Resque::enqueue('jobs', 'Failing_Job', null, true);
- $this->worker->work(0);
- $status = new Resque_Job_Status($token);
- $this->assertEquals(Resque_Job_Status::STATUS_FAILED, $status->get());
- }
-
- public function testCompletedJobReturnsCompletedStatus()
- {
- $token = Resque::enqueue('jobs', 'Test_Job', null, true);
- $this->worker->work(0);
- $status = new Resque_Job_Status($token);
- $this->assertEquals(Resque_Job_Status::STATUS_COMPLETE, $status->get());
- }
-
- public function testStatusIsNotTrackedWhenToldNotTo()
- {
- $token = Resque::enqueue('jobs', 'Test_Job', null, false);
- $status = new Resque_Job_Status($token);
- $this->assertFalse($status->isTracking());
- }
-
- public function testStatusTrackingCanBeStopped()
- {
- Resque_Job_Status::create('test');
- $status = new Resque_Job_Status('test');
- $this->assertEquals(Resque_Job_Status::STATUS_WAITING, $status->get());
- $status->stop();
- $this->assertFalse($status->get());
- }
-
- 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 = Resque_Job::reserve('jobs');
- $this->assertEquals(Resque_Job_Status::STATUS_WAITING, $newJob->getStatus());
- }
+ public function setUp()
+ {
+ parent::setUp();
+
+ // Register a worker to test with
+ $this->worker = new Resque_Worker('jobs');
+ $this->worker->setLogger(new Resque_Log());
+ }
+
+ public function testJobStatusCanBeTracked()
+ {
+ $token = Resque::enqueue('jobs', 'Test_Job', null, true);
+ $status = new Resque_Job_Status($token);
+ $this->assertTrue($status->isTracking());
+ }
+
+ public function testJobStatusIsReturnedViaJobInstance()
+ {
+ $token = Resque::enqueue('jobs', 'Test_Job', null, true);
+ $job = Resque_Job::reserve('jobs');
+ $this->assertEquals(Resque_Job_Status::STATUS_WAITING, $job->getStatus());
+ }
+
+ public function testQueuedJobReturnsQueuedStatus()
+ {
+ $token = Resque::enqueue('jobs', 'Test_Job', null, true);
+ $status = new Resque_Job_Status($token);
+ $this->assertEquals(Resque_Job_Status::STATUS_WAITING, $status->get());
+ }
+
+ public function testRunningJobReturnsRunningStatus()
+ {
+ $token = Resque::enqueue('jobs', 'Failing_Job', null, true);
+ $job = $this->worker->reserve();
+ $this->worker->workingOn($job);
+ $status = new Resque_Job_Status($token);
+ $this->assertEquals(Resque_Job_Status::STATUS_RUNNING, $status->get());
+ }
+
+ public function testFailedJobReturnsFailedStatus()
+ {
+ $token = Resque::enqueue('jobs', 'Failing_Job', null, true);
+ $this->worker->work(0);
+ $status = new Resque_Job_Status($token);
+ $this->assertEquals(Resque_Job_Status::STATUS_FAILED, $status->get());
+ }
+
+ public function testCompletedJobReturnsCompletedStatus()
+ {
+ $token = Resque::enqueue('jobs', 'Test_Job', null, true);
+ $this->worker->work(0);
+ $status = new Resque_Job_Status($token);
+ $this->assertEquals(Resque_Job_Status::STATUS_COMPLETE, $status->get());
+ }
+
+ public function testStatusIsNotTrackedWhenToldNotTo()
+ {
+ $token = Resque::enqueue('jobs', 'Test_Job', null, false);
+ $status = new Resque_Job_Status($token);
+ $this->assertFalse($status->isTracking());
+ }
+
+ public function testStatusTrackingCanBeStopped()
+ {
+ Resque_Job_Status::create('test');
+ $status = new Resque_Job_Status('test');
+ $this->assertEquals(Resque_Job_Status::STATUS_WAITING, $status->get());
+ $status->stop();
+ $this->assertFalse($status->get());
+ }
+
+ 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 = Resque_Job::reserve('jobs');
+ $this->assertEquals(Resque_Job_Status::STATUS_WAITING, $newJob->getStatus());
+ }
}
\ No newline at end of file
diff --git a/test/Resque/Tests/JobTest.php b/test/Resque/Tests/JobTest.php
index fb55d13b..04ad3a65 100644
--- a/test/Resque/Tests/JobTest.php
+++ b/test/Resque/Tests/JobTest.php
@@ -3,444 +3,445 @@
/**
* Resque_Job tests.
*
- * @package Resque/Tests
- * @author Chris Boulton
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Tests
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Tests_JobTest extends Resque_Tests_TestCase
{
- protected $worker;
-
- public function setUp()
- {
- parent::setUp();
-
- // Register a worker to test with
- $this->worker = new Resque_Worker('jobs');
- $this->worker->setLogger(new Resque_Log());
- $this->worker->registerWorker();
- }
-
- public function testJobCanBeQueued()
- {
- $this->assertTrue((bool)Resque::enqueue('jobs', 'Test_Job'));
- }
-
- /**
- * @expectedException Resque_RedisException
- */
- public function testRedisErrorThrowsExceptionOnJobCreation()
- {
- $mockCredis = $this->getMockBuilder('Credis_Client')
- ->setMethods(['connect', '__call'])
- ->getMock();
- $mockCredis->expects($this->any())->method('__call')
- ->will($this->throwException(new CredisException('failure')));
-
- Resque::setBackend(function($database) use ($mockCredis) {
- return new Resque_Redis('localhost:6379', $database, $mockCredis);
- });
- Resque::enqueue('jobs', 'This is a test');
- }
-
- public function testQeueuedJobCanBeReserved()
- {
- Resque::enqueue('jobs', 'Test_Job');
-
- $job = Resque_Job::reserve('jobs');
- if($job == false) {
- $this->fail('Job could not be reserved.');
- }
- $this->assertEquals('jobs', $job->queue);
- $this->assertEquals('Test_Job', $job->payload['class']);
- }
-
- /**
- * @expectedException InvalidArgumentException
- */
- public function testObjectArgumentsCannotBePassedToJob()
- {
- $args = new stdClass;
- $args->test = 'somevalue';
- Resque::enqueue('jobs', 'Test_Job', $args);
- }
-
- public function testQueuedJobReturnsExactSamePassedInArguments()
- {
- $args = array(
- 'int' => 123,
- 'numArray' => array(
- 1,
- 2,
- ),
- 'assocArray' => array(
- 'key1' => 'value1',
- 'key2' => 'value2'
- ),
- );
- Resque::enqueue('jobs', 'Test_Job', $args);
- $job = Resque_Job::reserve('jobs');
-
- $this->assertEquals($args, $job->getArguments());
- }
-
- public function testAfterJobIsReservedItIsRemoved()
- {
- Resque::enqueue('jobs', 'Test_Job');
- Resque_Job::reserve('jobs');
- $this->assertFalse(Resque_Job::reserve('jobs'));
- }
-
- public function testRecreatedJobMatchesExistingJob()
- {
- $args = array(
- 'int' => 123,
- 'numArray' => array(
- 1,
- 2,
- ),
- 'assocArray' => array(
- 'key1' => 'value1',
- 'key2' => 'value2'
- ),
- );
-
- Resque::enqueue('jobs', 'Test_Job', $args);
- $job = Resque_Job::reserve('jobs');
-
- // Now recreate it
- $job->recreate();
-
- $newJob = Resque_Job::reserve('jobs');
- $this->assertEquals($job->payload['class'], $newJob->payload['class']);
- $this->assertEquals($job->getArguments(), $newJob->getArguments());
- }
-
-
- public function testFailedJobExceptionsAreCaught()
- {
- $payload = array(
- 'class' => 'Failing_Job',
- 'args' => null
- );
- $job = new Resque_Job('jobs', $payload);
- $job->worker = $this->worker;
-
- $this->worker->perform($job);
-
- $this->assertEquals(1, Resque_Stat::get('failed'));
- $this->assertEquals(1, Resque_Stat::get('failed:'.$this->worker));
- }
-
- /**
- * @expectedException Resque_Exception
- */
- public function testJobWithoutPerformMethodThrowsException()
- {
- Resque::enqueue('jobs', 'Test_Job_Without_Perform_Method');
- $job = $this->worker->reserve();
- $job->worker = $this->worker;
- $job->perform();
- }
-
- /**
- * @expectedException Resque_Exception
- */
- public function testInvalidJobThrowsException()
- {
- Resque::enqueue('jobs', 'Invalid_Job');
- $job = $this->worker->reserve();
- $job->worker = $this->worker;
- $job->perform();
- }
-
- public function testJobWithSetUpCallbackFiresSetUp()
- {
- $payload = array(
- 'class' => 'Test_Job_With_SetUp',
- 'args' => array(
- 'somevar',
- 'somevar2',
- ),
- );
- $job = new Resque_Job('jobs', $payload);
- $job->perform();
-
- $this->assertTrue(Test_Job_With_SetUp::$called);
- }
-
- public function testJobWithTearDownCallbackFiresTearDown()
- {
- $payload = array(
- 'class' => 'Test_Job_With_TearDown',
- 'args' => array(
- 'somevar',
- 'somevar2',
- ),
- );
- $job = new Resque_Job('jobs', $payload);
- $job->perform();
-
- $this->assertTrue(Test_Job_With_TearDown::$called);
- }
-
- public function testNamespaceNaming() {
- $fixture = array(
- array('test' => 'more:than:one:with:', 'assertValue' => 'more:than:one:with:'),
- array('test' => 'more:than:one:without', 'assertValue' => 'more:than:one:without:'),
- array('test' => 'resque', 'assertValue' => 'resque:'),
- array('test' => 'resque:', 'assertValue' => 'resque:'),
- );
-
- foreach($fixture as $item) {
- Resque_Redis::prefix($item['test']);
- $this->assertEquals(Resque_Redis::getPrefix(), $item['assertValue']);
- }
- }
-
- public function testJobWithNamespace()
- {
- Resque_Redis::prefix('php');
- $queue = 'jobs';
- $payload = array('another_value');
- Resque::enqueue($queue, 'Test_Job_With_TearDown', $payload);
-
- $this->assertEquals(Resque::queues(), array('jobs'));
- $this->assertEquals(Resque::size($queue), 1);
-
- Resque_Redis::prefix('resque');
- $this->assertEquals(Resque::size($queue), 0);
- }
-
- public function testDequeueAll()
- {
- $queue = 'jobs';
- Resque::enqueue($queue, 'Test_Job_Dequeue');
- Resque::enqueue($queue, 'Test_Job_Dequeue');
- $this->assertEquals(Resque::size($queue), 2);
- $this->assertEquals(Resque::dequeue($queue), 2);
- $this->assertEquals(Resque::size($queue), 0);
- }
-
- public function testDequeueMakeSureNotDeleteOthers()
- {
- $queue = 'jobs';
- Resque::enqueue($queue, 'Test_Job_Dequeue');
- Resque::enqueue($queue, 'Test_Job_Dequeue');
- $other_queue = 'other_jobs';
- Resque::enqueue($other_queue, 'Test_Job_Dequeue');
- Resque::enqueue($other_queue, 'Test_Job_Dequeue');
- $this->assertEquals(Resque::size($queue), 2);
- $this->assertEquals(Resque::size($other_queue), 2);
- $this->assertEquals(Resque::dequeue($queue), 2);
- $this->assertEquals(Resque::size($queue), 0);
- $this->assertEquals(Resque::size($other_queue), 2);
- }
-
- public function testDequeueSpecificItem()
- {
- $queue = 'jobs';
- Resque::enqueue($queue, 'Test_Job_Dequeue1');
- Resque::enqueue($queue, 'Test_Job_Dequeue2');
- $this->assertEquals(Resque::size($queue), 2);
- $test = array('Test_Job_Dequeue2');
- $this->assertEquals(Resque::dequeue($queue, $test), 1);
- $this->assertEquals(Resque::size($queue), 1);
- }
-
- public function testDequeueSpecificMultipleItems()
- {
- $queue = 'jobs';
- Resque::enqueue($queue, 'Test_Job_Dequeue1');
- Resque::enqueue($queue, 'Test_Job_Dequeue2');
- Resque::enqueue($queue, 'Test_Job_Dequeue3');
- $this->assertEquals(Resque::size($queue), 3);
- $test = array('Test_Job_Dequeue2', 'Test_Job_Dequeue3');
- $this->assertEquals(Resque::dequeue($queue, $test), 2);
- $this->assertEquals(Resque::size($queue), 1);
- }
-
- public function testDequeueNonExistingItem()
- {
- $queue = 'jobs';
- Resque::enqueue($queue, 'Test_Job_Dequeue1');
- Resque::enqueue($queue, 'Test_Job_Dequeue2');
- Resque::enqueue($queue, 'Test_Job_Dequeue3');
- $this->assertEquals(Resque::size($queue), 3);
- $test = array('Test_Job_Dequeue4');
- $this->assertEquals(Resque::dequeue($queue, $test), 0);
- $this->assertEquals(Resque::size($queue), 3);
- }
-
- public function testDequeueNonExistingItem2()
- {
- $queue = 'jobs';
- Resque::enqueue($queue, 'Test_Job_Dequeue1');
- Resque::enqueue($queue, 'Test_Job_Dequeue2');
- Resque::enqueue($queue, 'Test_Job_Dequeue3');
- $this->assertEquals(Resque::size($queue), 3);
- $test = array('Test_Job_Dequeue4', 'Test_Job_Dequeue1');
- $this->assertEquals(Resque::dequeue($queue, $test), 1);
- $this->assertEquals(Resque::size($queue), 2);
- }
-
- public function testDequeueItemID()
- {
- $queue = 'jobs';
- Resque::enqueue($queue, 'Test_Job_Dequeue');
- $qid = Resque::enqueue($queue, 'Test_Job_Dequeue');
- $this->assertEquals(Resque::size($queue), 2);
- $test = array('Test_Job_Dequeue' => $qid);
- $this->assertEquals(Resque::dequeue($queue, $test), 1);
- $this->assertEquals(Resque::size($queue), 1);
- }
-
- public function testDequeueWrongItemID()
- {
- $queue = 'jobs';
- Resque::enqueue($queue, 'Test_Job_Dequeue');
- $qid = Resque::enqueue($queue, 'Test_Job_Dequeue');
- $this->assertEquals(Resque::size($queue), 2);
- #qid right but class name is wrong
- $test = array('Test_Job_Dequeue1' => $qid);
- $this->assertEquals(Resque::dequeue($queue, $test), 0);
- $this->assertEquals(Resque::size($queue), 2);
- }
-
- public function testDequeueWrongItemID2()
- {
- $queue = 'jobs';
- Resque::enqueue($queue, 'Test_Job_Dequeue');
- $qid = Resque::enqueue($queue, 'Test_Job_Dequeue');
- $this->assertEquals(Resque::size($queue), 2);
- $test = array('Test_Job_Dequeue' => 'r4nD0mH4sh3dId');
- $this->assertEquals(Resque::dequeue($queue, $test), 0);
- $this->assertEquals(Resque::size($queue), 2);
- }
-
- public function testDequeueItemWithArg()
- {
- $queue = 'jobs';
- $arg = array('foo' => 1, 'bar' => 2);
- Resque::enqueue($queue, 'Test_Job_Dequeue9');
- Resque::enqueue($queue, 'Test_Job_Dequeue9', $arg);
- $this->assertEquals(Resque::size($queue), 2);
- $test = array('Test_Job_Dequeue9' => $arg);
- $this->assertEquals(Resque::dequeue($queue, $test), 1);
- #$this->assertEquals(Resque::size($queue), 1);
- }
-
- public function testDequeueSeveralItemsWithArgs()
- {
- // GIVEN
- $queue = 'jobs';
- $args = array('foo' => 1, 'bar' => 10);
- $removeArgs = array('foo' => 1, 'bar' => 2);
- Resque::enqueue($queue, 'Test_Job_Dequeue9', $args);
- Resque::enqueue($queue, 'Test_Job_Dequeue9', $removeArgs);
- Resque::enqueue($queue, 'Test_Job_Dequeue9', $removeArgs);
- $this->assertEquals(Resque::size($queue), 3);
-
- // WHEN
- $test = array('Test_Job_Dequeue9' => $removeArgs);
- $removedItems = Resque::dequeue($queue, $test);
-
- // THEN
- $this->assertEquals($removedItems, 2);
- $this->assertEquals(Resque::size($queue), 1);
- $item = Resque::pop($queue);
- $this->assertInternalType('array', $item['args']);
- $this->assertEquals(10, $item['args'][0]['bar'], 'Wrong items were dequeued from queue!');
- }
-
- public function testDequeueItemWithUnorderedArg()
- {
- $queue = 'jobs';
- $arg = array('foo' => 1, 'bar' => 2);
- $arg2 = array('bar' => 2, 'foo' => 1);
- Resque::enqueue($queue, 'Test_Job_Dequeue');
- Resque::enqueue($queue, 'Test_Job_Dequeue', $arg);
- $this->assertEquals(Resque::size($queue), 2);
- $test = array('Test_Job_Dequeue' => $arg2);
- $this->assertEquals(Resque::dequeue($queue, $test), 1);
- $this->assertEquals(Resque::size($queue), 1);
- }
-
- public function testDequeueItemWithiWrongArg()
- {
- $queue = 'jobs';
- $arg = array('foo' => 1, 'bar' => 2);
- $arg2 = array('foo' => 2, 'bar' => 3);
- Resque::enqueue($queue, 'Test_Job_Dequeue');
- Resque::enqueue($queue, 'Test_Job_Dequeue', $arg);
- $this->assertEquals(Resque::size($queue), 2);
- $test = array('Test_Job_Dequeue' => $arg2);
- $this->assertEquals(Resque::dequeue($queue, $test), 0);
- $this->assertEquals(Resque::size($queue), 2);
- }
-
- public function testUseDefaultFactoryToGetJobInstance()
- {
- $payload = array(
- 'class' => 'Some_Job_Class',
- 'args' => null
- );
- $job = new Resque_Job('jobs', $payload);
- $instance = $job->getInstance();
- $this->assertInstanceOf('Some_Job_Class', $instance);
- }
-
- public function testUseFactoryToGetJobInstance()
- {
- $payload = array(
- 'class' => 'Some_Job_Class',
- 'args' => array(array())
- );
- $job = new Resque_Job('jobs', $payload);
- $factory = new Some_Stub_Factory();
- $job->setJobFactory($factory);
- $instance = $job->getInstance();
- $this->assertInstanceOf('Resque_JobInterface', $instance);
- }
-
- public function testDoNotUseFactoryToGetInstance()
- {
- $payload = array(
- 'class' => 'Some_Job_Class',
- 'args' => array(array())
- );
- $job = new Resque_Job('jobs', $payload);
- $factory = $this->getMock('Resque_Job_FactoryInterface');
- $testJob = $this->getMock('Resque_JobInterface');
- $factory->expects(self::never())->method('create')->will(self::returnValue($testJob));
- $instance = $job->getInstance();
- $this->assertInstanceOf('Resque_JobInterface', $instance);
- }
+ protected $worker;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ // Register a worker to test with
+ $this->worker = new Resque_Worker('jobs');
+ $this->worker->setLogger(new Resque_Log());
+ $this->worker->registerWorker();
+ }
+
+ public function testJobCanBeQueued()
+ {
+ $this->assertTrue((bool)Resque::enqueue('jobs', 'Test_Job'));
+ }
+
+ /**
+ * @expectedException Resque_RedisException
+ */
+ public function testRedisErrorThrowsExceptionOnJobCreation()
+ {
+ $mockCredis = $this->getMockBuilder('Credis_Client')
+ ->setMethods(['connect', '__call'])
+ ->getMock();
+ $mockCredis->expects($this->any())->method('__call')
+ ->will($this->throwException(new CredisException('failure')));
+
+ Resque::setBackend(function ($database) use ($mockCredis) {
+ return new Resque_Redis('localhost:6379', $database, $mockCredis);
+ });
+ Resque::enqueue('jobs', 'This is a test');
+ }
+
+ public function testQeueuedJobCanBeReserved()
+ {
+ Resque::enqueue('jobs', 'Test_Job');
+
+ $job = Resque_Job::reserve('jobs');
+ if ($job == false) {
+ $this->fail('Job could not be reserved.');
+ }
+ $this->assertEquals('jobs', $job->queue);
+ $this->assertEquals('Test_Job', $job->payload['class']);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testObjectArgumentsCannotBePassedToJob()
+ {
+ $args = new stdClass;
+ $args->test = 'somevalue';
+ Resque::enqueue('jobs', 'Test_Job', $args);
+ }
+
+ public function testQueuedJobReturnsExactSamePassedInArguments()
+ {
+ $args = [
+ 'int' => 123,
+ 'numArray' => [
+ 1,
+ 2
+ ],
+ 'assocArray' => [
+ 'key1' => 'value1',
+ 'key2' => 'value2'
+ ]
+ ];
+ Resque::enqueue('jobs', 'Test_Job', $args);
+ $job = Resque_Job::reserve('jobs');
+
+ $this->assertEquals($args, $job->getArguments());
+ }
+
+ public function testAfterJobIsReservedItIsRemoved()
+ {
+ Resque::enqueue('jobs', 'Test_Job');
+ Resque_Job::reserve('jobs');
+ $this->assertFalse(Resque_Job::reserve('jobs'));
+ }
+
+ public function testRecreatedJobMatchesExistingJob()
+ {
+ $args = [
+ 'int' => 123,
+ 'numArray' => [
+ 1,
+ 2
+ ],
+ 'assocArray' => [
+ 'key1' => 'value1',
+ 'key2' => 'value2'
+ ]
+ ];
+
+ Resque::enqueue('jobs', 'Test_Job', $args);
+ $job = Resque_Job::reserve('jobs');
+
+ // Now recreate it
+ $job->recreate();
+
+ $newJob = Resque_Job::reserve('jobs');
+ $this->assertEquals($job->payload['class'], $newJob->payload['class']);
+ $this->assertEquals($job->getArguments(), $newJob->getArguments());
+ }
+
+
+ public function testFailedJobExceptionsAreCaught()
+ {
+ $payload = [
+ 'class' => 'Failing_Job',
+ 'args' => null
+ ];
+ $job = new Resque_Job('jobs', $payload);
+ $job->worker = $this->worker;
+
+ $this->worker->perform($job);
+
+ $this->assertEquals(1, Resque_Stat::get('failed'));
+ $this->assertEquals(1, Resque_Stat::get('failed:' . $this->worker));
+ }
+
+ /**
+ * @expectedException Resque_Exception
+ */
+ public function testJobWithoutPerformMethodThrowsException()
+ {
+ Resque::enqueue('jobs', 'Test_Job_Without_Perform_Method');
+ $job = $this->worker->reserve();
+ $job->worker = $this->worker;
+ $job->perform();
+ }
+
+ /**
+ * @expectedException Resque_Exception
+ */
+ public function testInvalidJobThrowsException()
+ {
+ Resque::enqueue('jobs', 'Invalid_Job');
+ $job = $this->worker->reserve();
+ $job->worker = $this->worker;
+ $job->perform();
+ }
+
+ public function testJobWithSetUpCallbackFiresSetUp()
+ {
+ $payload = [
+ 'class' => 'Test_Job_With_SetUp',
+ 'args' => [
+ 'somevar',
+ 'somevar2'
+ ]
+ ];
+ $job = new Resque_Job('jobs', $payload);
+ $job->perform();
+
+ $this->assertTrue(Test_Job_With_SetUp::$called);
+ }
+
+ public function testJobWithTearDownCallbackFiresTearDown()
+ {
+ $payload = [
+ 'class' => 'Test_Job_With_TearDown',
+ 'args' => [
+ 'somevar',
+ 'somevar2'
+ ]
+ ];
+ $job = new Resque_Job('jobs', $payload);
+ $job->perform();
+
+ $this->assertTrue(Test_Job_With_TearDown::$called);
+ }
+
+ public function testNamespaceNaming()
+ {
+ $fixture = [
+ ['test' => 'more:than:one:with:', 'assertValue' => 'more:than:one:with:'],
+ ['test' => 'more:than:one:without', 'assertValue' => 'more:than:one:without:'],
+ ['test' => 'resque', 'assertValue' => 'resque:'],
+ ['test' => 'resque:', 'assertValue' => 'resque:']
+ ];
+
+ foreach ($fixture as $item) {
+ Resque_Redis::prefix($item['test']);
+ $this->assertEquals(Resque_Redis::getPrefix(), $item['assertValue']);
+ }
+ }
+
+ public function testJobWithNamespace()
+ {
+ Resque_Redis::prefix('php');
+ $queue = 'jobs';
+ $payload = ['another_value'];
+ Resque::enqueue($queue, 'Test_Job_With_TearDown', $payload);
+
+ $this->assertEquals(Resque::queues(), ['jobs']);
+ $this->assertEquals(Resque::size($queue), 1);
+
+ Resque_Redis::prefix('resque');
+ $this->assertEquals(Resque::size($queue), 0);
+ }
+
+ public function testDequeueAll()
+ {
+ $queue = 'jobs';
+ Resque::enqueue($queue, 'Test_Job_Dequeue');
+ Resque::enqueue($queue, 'Test_Job_Dequeue');
+ $this->assertEquals(Resque::size($queue), 2);
+ $this->assertEquals(Resque::dequeue($queue), 2);
+ $this->assertEquals(Resque::size($queue), 0);
+ }
+
+ public function testDequeueMakeSureNotDeleteOthers()
+ {
+ $queue = 'jobs';
+ Resque::enqueue($queue, 'Test_Job_Dequeue');
+ Resque::enqueue($queue, 'Test_Job_Dequeue');
+ $other_queue = 'other_jobs';
+ Resque::enqueue($other_queue, 'Test_Job_Dequeue');
+ Resque::enqueue($other_queue, 'Test_Job_Dequeue');
+ $this->assertEquals(Resque::size($queue), 2);
+ $this->assertEquals(Resque::size($other_queue), 2);
+ $this->assertEquals(Resque::dequeue($queue), 2);
+ $this->assertEquals(Resque::size($queue), 0);
+ $this->assertEquals(Resque::size($other_queue), 2);
+ }
+
+ public function testDequeueSpecificItem()
+ {
+ $queue = 'jobs';
+ Resque::enqueue($queue, 'Test_Job_Dequeue1');
+ Resque::enqueue($queue, 'Test_Job_Dequeue2');
+ $this->assertEquals(Resque::size($queue), 2);
+ $test = ['Test_Job_Dequeue2'];
+ $this->assertEquals(Resque::dequeue($queue, $test), 1);
+ $this->assertEquals(Resque::size($queue), 1);
+ }
+
+ public function testDequeueSpecificMultipleItems()
+ {
+ $queue = 'jobs';
+ Resque::enqueue($queue, 'Test_Job_Dequeue1');
+ Resque::enqueue($queue, 'Test_Job_Dequeue2');
+ Resque::enqueue($queue, 'Test_Job_Dequeue3');
+ $this->assertEquals(Resque::size($queue), 3);
+ $test = ['Test_Job_Dequeue2', 'Test_Job_Dequeue3'];
+ $this->assertEquals(Resque::dequeue($queue, $test), 2);
+ $this->assertEquals(Resque::size($queue), 1);
+ }
+
+ public function testDequeueNonExistingItem()
+ {
+ $queue = 'jobs';
+ Resque::enqueue($queue, 'Test_Job_Dequeue1');
+ Resque::enqueue($queue, 'Test_Job_Dequeue2');
+ Resque::enqueue($queue, 'Test_Job_Dequeue3');
+ $this->assertEquals(Resque::size($queue), 3);
+ $test = ['Test_Job_Dequeue4'];
+ $this->assertEquals(Resque::dequeue($queue, $test), 0);
+ $this->assertEquals(Resque::size($queue), 3);
+ }
+
+ public function testDequeueNonExistingItem2()
+ {
+ $queue = 'jobs';
+ Resque::enqueue($queue, 'Test_Job_Dequeue1');
+ Resque::enqueue($queue, 'Test_Job_Dequeue2');
+ Resque::enqueue($queue, 'Test_Job_Dequeue3');
+ $this->assertEquals(Resque::size($queue), 3);
+ $test = ['Test_Job_Dequeue4', 'Test_Job_Dequeue1'];
+ $this->assertEquals(Resque::dequeue($queue, $test), 1);
+ $this->assertEquals(Resque::size($queue), 2);
+ }
+
+ public function testDequeueItemID()
+ {
+ $queue = 'jobs';
+ Resque::enqueue($queue, 'Test_Job_Dequeue');
+ $qid = Resque::enqueue($queue, 'Test_Job_Dequeue');
+ $this->assertEquals(Resque::size($queue), 2);
+ $test = ['Test_Job_Dequeue' => $qid];
+ $this->assertEquals(Resque::dequeue($queue, $test), 1);
+ $this->assertEquals(Resque::size($queue), 1);
+ }
+
+ public function testDequeueWrongItemID()
+ {
+ $queue = 'jobs';
+ Resque::enqueue($queue, 'Test_Job_Dequeue');
+ $qid = Resque::enqueue($queue, 'Test_Job_Dequeue');
+ $this->assertEquals(Resque::size($queue), 2);
+ #qid right but class name is wrong
+ $test = ['Test_Job_Dequeue1' => $qid];
+ $this->assertEquals(Resque::dequeue($queue, $test), 0);
+ $this->assertEquals(Resque::size($queue), 2);
+ }
+
+ public function testDequeueWrongItemID2()
+ {
+ $queue = 'jobs';
+ Resque::enqueue($queue, 'Test_Job_Dequeue');
+ $qid = Resque::enqueue($queue, 'Test_Job_Dequeue');
+ $this->assertEquals(Resque::size($queue), 2);
+ $test = ['Test_Job_Dequeue' => 'r4nD0mH4sh3dId'];
+ $this->assertEquals(Resque::dequeue($queue, $test), 0);
+ $this->assertEquals(Resque::size($queue), 2);
+ }
+
+ public function testDequeueItemWithArg()
+ {
+ $queue = 'jobs';
+ $arg = ['foo' => 1, 'bar' => 2];
+ Resque::enqueue($queue, 'Test_Job_Dequeue9');
+ Resque::enqueue($queue, 'Test_Job_Dequeue9', $arg);
+ $this->assertEquals(Resque::size($queue), 2);
+ $test = ['Test_Job_Dequeue9' => $arg];
+ $this->assertEquals(Resque::dequeue($queue, $test), 1);
+ #$this->assertEquals(Resque::size($queue), 1);
+ }
+
+ public function testDequeueSeveralItemsWithArgs()
+ {
+ // GIVEN
+ $queue = 'jobs';
+ $args = ['foo' => 1, 'bar' => 10];
+ $removeArgs = ['foo' => 1, 'bar' => 2];
+ Resque::enqueue($queue, 'Test_Job_Dequeue9', $args);
+ Resque::enqueue($queue, 'Test_Job_Dequeue9', $removeArgs);
+ Resque::enqueue($queue, 'Test_Job_Dequeue9', $removeArgs);
+ $this->assertEquals(Resque::size($queue), 3);
+
+ // WHEN
+ $test = ['Test_Job_Dequeue9' => $removeArgs];
+ $removedItems = Resque::dequeue($queue, $test);
+
+ // THEN
+ $this->assertEquals($removedItems, 2);
+ $this->assertEquals(Resque::size($queue), 1);
+ $item = Resque::pop($queue);
+ $this->assertInternalType('array', $item['args']);
+ $this->assertEquals(10, $item['args'][0]['bar'], 'Wrong items were dequeued from queue!');
+ }
+
+ public function testDequeueItemWithUnorderedArg()
+ {
+ $queue = 'jobs';
+ $arg = ['foo' => 1, 'bar' => 2];
+ $arg2 = ['bar' => 2, 'foo' => 1];
+ Resque::enqueue($queue, 'Test_Job_Dequeue');
+ Resque::enqueue($queue, 'Test_Job_Dequeue', $arg);
+ $this->assertEquals(Resque::size($queue), 2);
+ $test = ['Test_Job_Dequeue' => $arg2];
+ $this->assertEquals(Resque::dequeue($queue, $test), 1);
+ $this->assertEquals(Resque::size($queue), 1);
+ }
+
+ public function testDequeueItemWithiWrongArg()
+ {
+ $queue = 'jobs';
+ $arg = ['foo' => 1, 'bar' => 2];
+ $arg2 = ['foo' => 2, 'bar' => 3];
+ Resque::enqueue($queue, 'Test_Job_Dequeue');
+ Resque::enqueue($queue, 'Test_Job_Dequeue', $arg);
+ $this->assertEquals(Resque::size($queue), 2);
+ $test = ['Test_Job_Dequeue' => $arg2];
+ $this->assertEquals(Resque::dequeue($queue, $test), 0);
+ $this->assertEquals(Resque::size($queue), 2);
+ }
+
+ public function testUseDefaultFactoryToGetJobInstance()
+ {
+ $payload = [
+ 'class' => 'Some_Job_Class',
+ 'args' => null
+ ];
+ $job = new Resque_Job('jobs', $payload);
+ $instance = $job->getInstance();
+ $this->assertInstanceOf('Some_Job_Class', $instance);
+ }
+
+ public function testUseFactoryToGetJobInstance()
+ {
+ $payload = [
+ 'class' => 'Some_Job_Class',
+ 'args' => [[]]
+ ];
+ $job = new Resque_Job('jobs', $payload);
+ $factory = new Some_Stub_Factory();
+ $job->setJobFactory($factory);
+ $instance = $job->getInstance();
+ $this->assertInstanceOf('Resque_JobInterface', $instance);
+ }
+
+ public function testDoNotUseFactoryToGetInstance()
+ {
+ $payload = [
+ 'class' => 'Some_Job_Class',
+ 'args' => [[]]
+ ];
+ $job = new Resque_Job('jobs', $payload);
+ $factory = $this->getMock('Resque_Job_FactoryInterface');
+ $testJob = $this->getMock('Resque_JobInterface');
+ $factory->expects(self::never())->method('create')->will(self::returnValue($testJob));
+ $instance = $job->getInstance();
+ $this->assertInstanceOf('Resque_JobInterface', $instance);
+ }
}
class Some_Job_Class implements Resque_JobInterface
{
- /**
- * @return bool
- */
- public function perform()
- {
- return true;
- }
+ /**
+ * @return bool
+ */
+ public function perform()
+ {
+ return true;
+ }
}
class Some_Stub_Factory implements Resque_Job_FactoryInterface
{
- /**
- * @param $className
- * @param array $args
- * @param $queue
- * @return Resque_JobInterface
- */
- public function create($className, $args, $queue)
- {
- return new Some_Job_Class();
- }
+ /**
+ * @param $className
+ * @param array $args
+ * @param $queue
+ * @return Resque_JobInterface
+ */
+ public function create($className, $args, $queue)
+ {
+ return new Some_Job_Class();
+ }
}
diff --git a/test/Resque/Tests/LogTest.php b/test/Resque/Tests/LogTest.php
index db97b160..f7f571da 100644
--- a/test/Resque/Tests/LogTest.php
+++ b/test/Resque/Tests/LogTest.php
@@ -1,31 +1,32 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Tests
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Tests_LogTest extends Resque_Tests_TestCase
{
- public function testLogInterpolate()
- {
- $logger = new Resque_Log();
- $actual = $logger->interpolate('string {replace}', array('replace' => 'value'));
- $expected = 'string value';
+ public function testLogInterpolate()
+ {
+ $logger = new Resque_Log();
+ $actual = $logger->interpolate('string {replace}', ['replace' => 'value']);
+ $expected = 'string value';
- $this->assertEquals($expected, $actual);
- }
+ $this->assertEquals($expected, $actual);
+ }
- public function testLogInterpolateMutiple()
- {
- $logger = new Resque_Log();
- $actual = $logger->interpolate(
- 'string {replace1} {replace2}',
- array('replace1' => 'value1', 'replace2' => 'value2')
- );
- $expected = 'string value1 value2';
+ public function testLogInterpolateMutiple()
+ {
+ $logger = new Resque_Log();
+ $actual = $logger->interpolate(
+ 'string {replace1} {replace2}',
+ ['replace1' => 'value1', 'replace2' => 'value2']
+ );
+ $expected = 'string value1 value2';
- $this->assertEquals($expected, $actual);
- }
+ $this->assertEquals($expected, $actual);
+ }
}
diff --git a/test/Resque/Tests/RedisTest.php b/test/Resque/Tests/RedisTest.php
index 55b5e17d..03cf08a5 100644
--- a/test/Resque/Tests/RedisTest.php
+++ b/test/Resque/Tests/RedisTest.php
@@ -1,197 +1,270 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Tests
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Tests_RedisTest extends Resque_Tests_TestCase
{
- /**
- * @expectedException Resque_RedisException
- */
- public function testRedisExceptionsAreSurfaced()
- {
- $mockCredis = $this->getMockBuilder('Credis_Client')
- ->setMethods(['connect', '__call'])
- ->getMock();
- $mockCredis->expects($this->any())->method('__call')
- ->will($this->throwException(new CredisException('failure')));
+ /**
+ * @expectedException Resque_RedisException
+ */
+ public function testRedisExceptionsAreSurfaced()
+ {
+ $mockCredis = $this->getMockBuilder('Credis_Client')
+ ->setMethods(['connect', '__call'])
+ ->getMock();
+ $mockCredis->expects($this->any())->method('__call')
+ ->will($this->throwException(new CredisException('failure')));
- Resque::setBackend(function($database) use ($mockCredis) {
- return new Resque_Redis('localhost:6379', $database, $mockCredis);
- });
- Resque::redis()->ping();
- }
+ Resque::setBackend(function ($database) use ($mockCredis) {
+ return new Resque_Redis('localhost:6379', $database, $mockCredis);
+ });
+ Resque::redis()->ping();
+ }
- /**
- * These DNS strings are considered valid.
- *
- * @return array
- */
- public function validDsnStringProvider()
- {
- return array(
- // Input , Expected output
- array('', array(
- 'localhost',
- Resque_Redis::DEFAULT_PORT,
- false,
- false, false,
- array(),
- )),
- array('localhost', array(
- 'localhost',
- Resque_Redis::DEFAULT_PORT,
- false,
- false, false,
- array(),
- )),
- array('localhost:1234', array(
- 'localhost',
- 1234,
- false,
- false, false,
- array(),
- )),
- array('localhost:1234/2', array(
- 'localhost',
- 1234,
- 2,
- false, false,
- array(),
- )),
- array('redis://foobar', array(
- 'foobar',
- Resque_Redis::DEFAULT_PORT,
- false,
- false, false,
- array(),
- )),
- array('redis://foobar/', array(
- 'foobar',
- Resque_Redis::DEFAULT_PORT,
- false,
- false, false,
- array(),
- )),
- array('redis://foobar:1234', array(
- 'foobar',
- 1234,
- false,
- false, false,
- array(),
- )),
- array('redis://foobar:1234/15', array(
- 'foobar',
- 1234,
- 15,
- false, false,
- array(),
- )),
- array('redis://foobar:1234/0', array(
- 'foobar',
- 1234,
- 0,
- false, false,
- array(),
- )),
- array('redis://user@foobar:1234', array(
- 'foobar',
- 1234,
- false,
- 'user', false,
- array(),
- )),
- array('redis://user@foobar:1234/15', array(
- 'foobar',
- 1234,
- 15,
- 'user', false,
- array(),
- )),
- array('redis://user:pass@foobar:1234', array(
- 'foobar',
- 1234,
- false,
- 'user', 'pass',
- array(),
- )),
- array('redis://user:pass@foobar:1234?x=y&a=b', array(
- 'foobar',
- 1234,
- false,
- 'user', 'pass',
- array('x' => 'y', 'a' => 'b'),
- )),
- array('redis://:pass@foobar:1234?x=y&a=b', array(
- 'foobar',
- 1234,
- false,
- false, 'pass',
- array('x' => 'y', 'a' => 'b'),
- )),
- array('redis://user@foobar:1234?x=y&a=b', array(
- 'foobar',
- 1234,
- false,
- 'user', false,
- array('x' => 'y', 'a' => 'b'),
- )),
- array('redis://foobar:1234?x=y&a=b', array(
- 'foobar',
- 1234,
- false,
- false, false,
- array('x' => 'y', 'a' => 'b'),
- )),
- array('redis://user@foobar:1234/12?x=y&a=b', array(
- 'foobar',
- 1234,
- 12,
- 'user', false,
- array('x' => 'y', 'a' => 'b'),
- )),
- array('tcp://user@foobar:1234/12?x=y&a=b', array(
- 'foobar',
- 1234,
- 12,
- 'user', false,
- array('x' => 'y', 'a' => 'b'),
- )),
- );
- }
+ /**
+ * These DNS strings are considered valid.
+ *
+ * @return array
+ */
+ public function validDsnStringProvider()
+ {
+ return [
+ // Input , Expected output
+ [
+ '',
+ [
+ 'localhost',
+ Resque_Redis::DEFAULT_PORT,
+ false,
+ false,
+ false,
+ []
+ ]
+ ],
+ [
+ 'localhost',
+ [
+ 'localhost',
+ Resque_Redis::DEFAULT_PORT,
+ false,
+ false,
+ false,
+ []
+ ]
+ ],
+ [
+ 'localhost:1234',
+ [
+ 'localhost',
+ 1234,
+ false,
+ false,
+ false,
+ []
+ ]
+ ],
+ [
+ 'localhost:1234/2',
+ [
+ 'localhost',
+ 1234,
+ 2,
+ false,
+ false,
+ []
+ ]
+ ],
+ [
+ 'redis://foobar',
+ [
+ 'foobar',
+ Resque_Redis::DEFAULT_PORT,
+ false,
+ false,
+ false,
+ []
+ ]
+ ],
+ [
+ 'redis://foobar/',
+ [
+ 'foobar',
+ Resque_Redis::DEFAULT_PORT,
+ false,
+ false,
+ false,
+ []
+ ]
+ ],
+ [
+ 'redis://foobar:1234',
+ [
+ 'foobar',
+ 1234,
+ false,
+ false,
+ false,
+ []
+ ]
+ ],
+ [
+ 'redis://foobar:1234/15',
+ [
+ 'foobar',
+ 1234,
+ 15,
+ false,
+ false,
+ []
+ ]
+ ],
+ [
+ 'redis://foobar:1234/0',
+ [
+ 'foobar',
+ 1234,
+ 0,
+ false,
+ false,
+ []
+ ]
+ ],
+ [
+ 'redis://user@foobar:1234',
+ [
+ 'foobar',
+ 1234,
+ false,
+ 'user',
+ false,
+ []
+ ]
+ ],
+ [
+ 'redis://user@foobar:1234/15',
+ [
+ 'foobar',
+ 1234,
+ 15,
+ 'user',
+ false,
+ []
+ ]
+ ],
+ [
+ 'redis://user:pass@foobar:1234',
+ [
+ 'foobar',
+ 1234,
+ false,
+ 'user',
+ 'pass',
+ []
+ ]
+ ],
+ [
+ 'redis://user:pass@foobar:1234?x=y&a=b',
+ [
+ 'foobar',
+ 1234,
+ false,
+ 'user',
+ 'pass',
+ ['x' => 'y', 'a' => 'b']
+ ]
+ ],
+ [
+ 'redis://:pass@foobar:1234?x=y&a=b',
+ [
+ 'foobar',
+ 1234,
+ false,
+ false,
+ 'pass',
+ ['x' => 'y', 'a' => 'b']
+ ]
+ ],
+ [
+ 'redis://user@foobar:1234?x=y&a=b',
+ [
+ 'foobar',
+ 1234,
+ false,
+ 'user',
+ false,
+ ['x' => 'y', 'a' => 'b']
+ ]
+ ],
+ [
+ 'redis://foobar:1234?x=y&a=b',
+ [
+ 'foobar',
+ 1234,
+ false,
+ false,
+ false,
+ ['x' => 'y', 'a' => 'b']
+ ]
+ ],
+ [
+ 'redis://user@foobar:1234/12?x=y&a=b',
+ [
+ 'foobar',
+ 1234,
+ 12,
+ 'user',
+ false,
+ ['x' => 'y', 'a' => 'b']
+ ]
+ ],
+ [
+ 'tcp://user@foobar:1234/12?x=y&a=b',
+ [
+ 'foobar',
+ 1234,
+ 12,
+ 'user',
+ false,
+ ['x' => 'y', 'a' => 'b']
+ ]
+ ]
+ ];
+ }
- /**
- * These DSN values should throw exceptions
- * @return array
- */
- public function bogusDsnStringProvider()
- {
- return array(
- array('http://foo.bar/'),
- array('user:@foobar:1234?x=y&a=b'),
- array('foobar:1234?x=y&a=b'),
- );
- }
+ /**
+ * These DSN values should throw exceptions
+ * @return array
+ */
+ public function bogusDsnStringProvider()
+ {
+ return [
+ ['http://foo.bar/'],
+ ['user:@foobar:1234?x=y&a=b'],
+ ['foobar:1234?x=y&a=b']
+ ];
+ }
- /**
- * @dataProvider validDsnStringProvider
- */
- public function testParsingValidDsnString($dsn, $expected)
- {
- $result = Resque_Redis::parseDsn($dsn);
- $this->assertEquals($expected, $result);
- }
+ /**
+ * @dataProvider validDsnStringProvider
+ */
+ public function testParsingValidDsnString($dsn, $expected)
+ {
+ $result = Resque_Redis::parseDsn($dsn);
+ $this->assertEquals($expected, $result);
+ }
- /**
- * @dataProvider bogusDsnStringProvider
- * @expectedException InvalidArgumentException
- */
- public function testParsingBogusDsnStringThrowsException($dsn)
- {
- // The next line should throw an InvalidArgumentException
- $result = Resque_Redis::parseDsn($dsn);
- }
+ /**
+ * @dataProvider bogusDsnStringProvider
+ * @expectedException InvalidArgumentException
+ */
+ public function testParsingBogusDsnStringThrowsException($dsn)
+ {
+ // The next line should throw an InvalidArgumentException
+ $result = Resque_Redis::parseDsn($dsn);
+ }
}
\ No newline at end of file
diff --git a/test/Resque/Tests/StatTest.php b/test/Resque/Tests/StatTest.php
index aa418887..5d505360 100644
--- a/test/Resque/Tests/StatTest.php
+++ b/test/Resque/Tests/StatTest.php
@@ -1,49 +1,50 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Tests
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Tests_StatTest extends Resque_Tests_TestCase
{
- public function testStatCanBeIncremented()
- {
- Resque_Stat::incr('test_incr');
- Resque_Stat::incr('test_incr');
- $this->assertEquals(2, $this->redis->get('resque:stat:test_incr'));
- }
+ public function testStatCanBeIncremented()
+ {
+ Resque_Stat::incr('test_incr');
+ Resque_Stat::incr('test_incr');
+ $this->assertEquals(2, $this->redis->get('resque:stat:test_incr'));
+ }
- public function testStatCanBeIncrementedByX()
- {
- Resque_Stat::incr('test_incrX', 10);
- Resque_Stat::incr('test_incrX', 11);
- $this->assertEquals(21, $this->redis->get('resque:stat:test_incrX'));
- }
+ public function testStatCanBeIncrementedByX()
+ {
+ Resque_Stat::incr('test_incrX', 10);
+ Resque_Stat::incr('test_incrX', 11);
+ $this->assertEquals(21, $this->redis->get('resque:stat:test_incrX'));
+ }
- public function testStatCanBeDecremented()
- {
- Resque_Stat::incr('test_decr', 22);
- Resque_Stat::decr('test_decr');
- $this->assertEquals(21, $this->redis->get('resque:stat:test_decr'));
- }
+ public function testStatCanBeDecremented()
+ {
+ Resque_Stat::incr('test_decr', 22);
+ Resque_Stat::decr('test_decr');
+ $this->assertEquals(21, $this->redis->get('resque:stat:test_decr'));
+ }
- public function testStatCanBeDecrementedByX()
- {
- Resque_Stat::incr('test_decrX', 22);
- Resque_Stat::decr('test_decrX', 11);
- $this->assertEquals(11, $this->redis->get('resque:stat:test_decrX'));
- }
+ public function testStatCanBeDecrementedByX()
+ {
+ Resque_Stat::incr('test_decrX', 22);
+ Resque_Stat::decr('test_decrX', 11);
+ $this->assertEquals(11, $this->redis->get('resque:stat:test_decrX'));
+ }
- public function testGetStatByName()
- {
- Resque_Stat::incr('test_get', 100);
- $this->assertEquals(100, Resque_Stat::get('test_get'));
- }
+ public function testGetStatByName()
+ {
+ Resque_Stat::incr('test_get', 100);
+ $this->assertEquals(100, Resque_Stat::get('test_get'));
+ }
- public function testGetUnknownStatReturns0()
- {
- $this->assertEquals(0, Resque_Stat::get('test_get_unknown'));
- }
+ public function testGetUnknownStatReturns0()
+ {
+ $this->assertEquals(0, Resque_Stat::get('test_get_unknown'));
+ }
}
\ No newline at end of file
diff --git a/test/Resque/Tests/TestCase.php b/test/Resque/Tests/TestCase.php
index a97f64bf..681842bd 100644
--- a/test/Resque/Tests/TestCase.php
+++ b/test/Resque/Tests/TestCase.php
@@ -1,30 +1,31 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Tests
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Tests_TestCase extends PHPUnit_Framework_TestCase
{
- protected $resque;
- protected $redis;
+ protected $resque;
+ protected $redis;
- public static function setUpBeforeClass()
- {
- date_default_timezone_set('UTC');
- }
+ public static function setUpBeforeClass()
+ {
+ date_default_timezone_set('UTC');
+ }
- public function setUp()
- {
- $config = file_get_contents(REDIS_CONF);
- preg_match('#^\s*port\s+([0-9]+)#m', $config, $matches);
- $this->redis = new Credis_Client('localhost', $matches[1]);
+ public function setUp()
+ {
+ $config = file_get_contents(REDIS_CONF);
+ preg_match('#^\s*port\s+([0-9]+)#m', $config, $matches);
+ $this->redis = new Credis_Client('localhost', $matches[1]);
- Resque::setBackend('redis://localhost:' . $matches[1]);
+ Resque::setBackend('redis://localhost:' . $matches[1]);
- // Flush redis
- $this->redis->flushAll();
- }
+ // Flush redis
+ $this->redis->flushAll();
+ }
}
diff --git a/test/Resque/Tests/WorkerTest.php b/test/Resque/Tests/WorkerTest.php
index 93c0621a..ac7fba20 100644
--- a/test/Resque/Tests/WorkerTest.php
+++ b/test/Resque/Tests/WorkerTest.php
@@ -1,287 +1,287 @@
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Tests
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Tests_WorkerTest extends Resque_Tests_TestCase
{
- public function testWorkerRegistersInList()
- {
- $worker = new Resque_Worker('*');
- $worker->setLogger(new Resque_Log());
- $worker->registerWorker();
-
- // Make sure the worker is in the list
- $this->assertTrue((bool)$this->redis->sismember('resque:workers', (string)$worker));
- }
-
- public function testGetAllWorkers()
- {
- $num = 3;
- // Register a few workers
- for($i = 0; $i < $num; ++$i) {
- $worker = new Resque_Worker('queue_' . $i);
- $worker->setLogger(new Resque_Log());
- $worker->registerWorker();
- }
-
- // Now try to get them
- $this->assertEquals($num, count(Resque_Worker::all()));
- }
-
- public function testGetWorkerById()
- {
- $worker = new Resque_Worker('*');
- $worker->setLogger(new Resque_Log());
- $worker->registerWorker();
-
- $newWorker = Resque_Worker::find((string)$worker);
- $this->assertEquals((string)$worker, (string)$newWorker);
- }
-
- public function testInvalidWorkerDoesNotExist()
- {
- $this->assertFalse(Resque_Worker::exists('blah'));
- }
-
- public function testWorkerCanUnregister()
- {
- $worker = new Resque_Worker('*');
- $worker->setLogger(new Resque_Log());
- $worker->registerWorker();
- $worker->unregisterWorker();
-
- $this->assertFalse(Resque_Worker::exists((string)$worker));
- $this->assertEquals(array(), Resque_Worker::all());
- $this->assertEquals(array(), $this->redis->smembers('resque:workers'));
- }
-
- public function testPausedWorkerDoesNotPickUpJobs()
- {
- $worker = new Resque_Worker('*');
- $worker->setLogger(new Resque_Log());
- $worker->pauseProcessing();
- Resque::enqueue('jobs', 'Test_Job');
- $worker->work(0);
- $worker->work(0);
- $this->assertEquals(0, Resque_Stat::get('processed'));
- }
-
- public function testResumedWorkerPicksUpJobs()
- {
- $worker = new Resque_Worker('*');
- $worker->setLogger(new Resque_Log());
- $worker->pauseProcessing();
- Resque::enqueue('jobs', 'Test_Job');
- $worker->work(0);
- $this->assertEquals(0, Resque_Stat::get('processed'));
- $worker->unPauseProcessing();
- $worker->work(0);
- $this->assertEquals(1, Resque_Stat::get('processed'));
- }
-
- public function testWorkerCanWorkOverMultipleQueues()
- {
- $worker = new Resque_Worker(array(
- 'queue1',
- 'queue2'
- ));
- $worker->setLogger(new Resque_Log());
- $worker->registerWorker();
- Resque::enqueue('queue1', 'Test_Job_1');
- Resque::enqueue('queue2', 'Test_Job_2');
-
- $job = $worker->reserve();
- $this->assertEquals('queue1', $job->queue);
-
- $job = $worker->reserve();
- $this->assertEquals('queue2', $job->queue);
- }
-
- public function testWorkerWorksQueuesInSpecifiedOrder()
- {
- $worker = new Resque_Worker(array(
- 'high',
- 'medium',
- 'low'
- ));
- $worker->setLogger(new Resque_Log());
- $worker->registerWorker();
-
- // Queue the jobs in a different order
- Resque::enqueue('low', 'Test_Job_1');
- Resque::enqueue('high', 'Test_Job_2');
- Resque::enqueue('medium', 'Test_Job_3');
-
- // Now check we get the jobs back in the right order
- $job = $worker->reserve();
- $this->assertEquals('high', $job->queue);
-
- $job = $worker->reserve();
- $this->assertEquals('medium', $job->queue);
-
- $job = $worker->reserve();
- $this->assertEquals('low', $job->queue);
- }
-
- public function testWildcardQueueWorkerWorksAllQueues()
- {
- $worker = new Resque_Worker('*');
- $worker->setLogger(new Resque_Log());
- $worker->registerWorker();
-
- Resque::enqueue('queue1', 'Test_Job_1');
- Resque::enqueue('queue2', 'Test_Job_2');
-
- $job = $worker->reserve();
- $this->assertEquals('queue1', $job->queue);
-
- $job = $worker->reserve();
- $this->assertEquals('queue2', $job->queue);
- }
-
- public function testWorkerDoesNotWorkOnUnknownQueues()
- {
- $worker = new Resque_Worker('queue1');
- $worker->setLogger(new Resque_Log());
- $worker->registerWorker();
- Resque::enqueue('queue2', 'Test_Job');
-
- $this->assertFalse($worker->reserve());
- }
-
- public function testWorkerClearsItsStatusWhenNotWorking()
- {
- Resque::enqueue('jobs', 'Test_Job');
- $worker = new Resque_Worker('jobs');
- $worker->setLogger(new Resque_Log());
- $job = $worker->reserve();
- $worker->workingOn($job);
- $worker->doneWorking();
- $this->assertEquals(array(), $worker->job());
- }
-
- public function testWorkerRecordsWhatItIsWorkingOn()
- {
- $worker = new Resque_Worker('jobs');
- $worker->setLogger(new Resque_Log());
- $worker->registerWorker();
-
- $payload = array(
- 'class' => 'Test_Job'
- );
- $job = new Resque_Job('jobs', $payload);
- $worker->workingOn($job);
-
- $job = $worker->job();
- $this->assertEquals('jobs', $job['queue']);
- if(!isset($job['run_at'])) {
- $this->fail('Job does not have run_at time');
- }
- $this->assertEquals($payload, $job['payload']);
- }
-
- public function testWorkerErasesItsStatsWhenShutdown()
- {
- Resque::enqueue('jobs', 'Test_Job');
- Resque::enqueue('jobs', 'Invalid_Job');
-
- $worker = new Resque_Worker('jobs');
- $worker->setLogger(new Resque_Log());
- $worker->work(0);
- $worker->work(0);
-
- $this->assertEquals(0, $worker->getStat('processed'));
- $this->assertEquals(0, $worker->getStat('failed'));
- }
-
- public function testWorkerCleansUpDeadWorkersOnStartup()
- {
- // Register a good worker
- $goodWorker = new Resque_Worker('jobs');
- $goodWorker->setLogger(new Resque_Log());
- $goodWorker->registerWorker();
- $workerId = explode(':', $goodWorker);
-
- // Register some bad workers
- $worker = new Resque_Worker('jobs');
- $worker->setLogger(new Resque_Log());
- $worker->setId($workerId[0].':1:jobs');
- $worker->registerWorker();
-
- $worker = new Resque_Worker(array('high', 'low'));
- $worker->setLogger(new Resque_Log());
- $worker->setId($workerId[0].':2:high,low');
- $worker->registerWorker();
-
- $this->assertEquals(3, count(Resque_Worker::all()));
-
- $goodWorker->pruneDeadWorkers();
-
- // There should only be $goodWorker left now
- $this->assertEquals(1, count(Resque_Worker::all()));
- }
-
- public function testDeadWorkerCleanUpDoesNotCleanUnknownWorkers()
- {
- // Register a bad worker on this machine
- $worker = new Resque_Worker('jobs');
- $worker->setLogger(new Resque_Log());
- $workerId = explode(':', $worker);
- $worker->setId($workerId[0].':1:jobs');
- $worker->registerWorker();
-
- // Register some other false workers
- $worker = new Resque_Worker('jobs');
- $worker->setLogger(new Resque_Log());
- $worker->setId('my.other.host:1:jobs');
- $worker->registerWorker();
-
- $this->assertEquals(2, count(Resque_Worker::all()));
-
- $worker->pruneDeadWorkers();
-
- // my.other.host should be left
- $workers = Resque_Worker::all();
- $this->assertEquals(1, count($workers));
- $this->assertEquals((string)$worker, (string)$workers[0]);
- }
-
- public function testWorkerFailsUncompletedJobsOnExit()
- {
- $worker = new Resque_Worker('jobs');
- $worker->setLogger(new Resque_Log());
- $worker->registerWorker();
-
- $payload = array(
- 'class' => 'Test_Job'
- );
- $job = new Resque_Job('jobs', $payload);
-
- $worker->workingOn($job);
- $worker->unregisterWorker();
-
- $this->assertEquals(1, Resque_Stat::get('failed'));
- }
+ public function testWorkerRegistersInList()
+ {
+ $worker = new Resque_Worker('*');
+ $worker->setLogger(new Resque_Log());
+ $worker->registerWorker();
+
+ // Make sure the worker is in the list
+ $this->assertTrue((bool)$this->redis->sismember('resque:workers', (string)$worker));
+ }
+
+ public function testGetAllWorkers()
+ {
+ $num = 3;
+ // Register a few workers
+ for ($i = 0; $i < $num; ++$i) {
+ $worker = new Resque_Worker('queue_' . $i);
+ $worker->setLogger(new Resque_Log());
+ $worker->registerWorker();
+ }
+
+ // Now try to get them
+ $this->assertEquals($num, count(Resque_Worker::all()));
+ }
+
+ public function testGetWorkerById()
+ {
+ $worker = new Resque_Worker('*');
+ $worker->setLogger(new Resque_Log());
+ $worker->registerWorker();
+
+ $newWorker = Resque_Worker::find((string)$worker);
+ $this->assertEquals((string)$worker, (string)$newWorker);
+ }
+
+ public function testInvalidWorkerDoesNotExist()
+ {
+ $this->assertFalse(Resque_Worker::exists('blah'));
+ }
+
+ public function testWorkerCanUnregister()
+ {
+ $worker = new Resque_Worker('*');
+ $worker->setLogger(new Resque_Log());
+ $worker->registerWorker();
+ $worker->unregisterWorker();
+
+ $this->assertFalse(Resque_Worker::exists((string)$worker));
+ $this->assertEquals([], Resque_Worker::all());
+ $this->assertEquals([], $this->redis->smembers('resque:workers'));
+ }
+
+ public function testPausedWorkerDoesNotPickUpJobs()
+ {
+ $worker = new Resque_Worker('*');
+ $worker->setLogger(new Resque_Log());
+ $worker->pauseProcessing();
+ Resque::enqueue('jobs', 'Test_Job');
+ $worker->work(0);
+ $worker->work(0);
+ $this->assertEquals(0, Resque_Stat::get('processed'));
+ }
+
+ public function testResumedWorkerPicksUpJobs()
+ {
+ $worker = new Resque_Worker('*');
+ $worker->setLogger(new Resque_Log());
+ $worker->pauseProcessing();
+ Resque::enqueue('jobs', 'Test_Job');
+ $worker->work(0);
+ $this->assertEquals(0, Resque_Stat::get('processed'));
+ $worker->unPauseProcessing();
+ $worker->work(0);
+ $this->assertEquals(1, Resque_Stat::get('processed'));
+ }
+
+ public function testWorkerCanWorkOverMultipleQueues()
+ {
+ $worker = new Resque_Worker([
+ 'queue1',
+ 'queue2'
+ ]);
+ $worker->setLogger(new Resque_Log());
+ $worker->registerWorker();
+ Resque::enqueue('queue1', 'Test_Job_1');
+ Resque::enqueue('queue2', 'Test_Job_2');
+
+ $job = $worker->reserve();
+ $this->assertEquals('queue1', $job->queue);
+
+ $job = $worker->reserve();
+ $this->assertEquals('queue2', $job->queue);
+ }
+
+ public function testWorkerWorksQueuesInSpecifiedOrder()
+ {
+ $worker = new Resque_Worker([
+ 'high',
+ 'medium',
+ 'low'
+ ]);
+ $worker->setLogger(new Resque_Log());
+ $worker->registerWorker();
+
+ // Queue the jobs in a different order
+ Resque::enqueue('low', 'Test_Job_1');
+ Resque::enqueue('high', 'Test_Job_2');
+ Resque::enqueue('medium', 'Test_Job_3');
+
+ // Now check we get the jobs back in the right order
+ $job = $worker->reserve();
+ $this->assertEquals('high', $job->queue);
+
+ $job = $worker->reserve();
+ $this->assertEquals('medium', $job->queue);
+
+ $job = $worker->reserve();
+ $this->assertEquals('low', $job->queue);
+ }
+
+ public function testWildcardQueueWorkerWorksAllQueues()
+ {
+ $worker = new Resque_Worker('*');
+ $worker->setLogger(new Resque_Log());
+ $worker->registerWorker();
+
+ Resque::enqueue('queue1', 'Test_Job_1');
+ Resque::enqueue('queue2', 'Test_Job_2');
+
+ $job = $worker->reserve();
+ $this->assertEquals('queue1', $job->queue);
+
+ $job = $worker->reserve();
+ $this->assertEquals('queue2', $job->queue);
+ }
+
+ public function testWorkerDoesNotWorkOnUnknownQueues()
+ {
+ $worker = new Resque_Worker('queue1');
+ $worker->setLogger(new Resque_Log());
+ $worker->registerWorker();
+ Resque::enqueue('queue2', 'Test_Job');
+
+ $this->assertFalse($worker->reserve());
+ }
+
+ public function testWorkerClearsItsStatusWhenNotWorking()
+ {
+ Resque::enqueue('jobs', 'Test_Job');
+ $worker = new Resque_Worker('jobs');
+ $worker->setLogger(new Resque_Log());
+ $job = $worker->reserve();
+ $worker->workingOn($job);
+ $worker->doneWorking();
+ $this->assertEquals([], $worker->job());
+ }
+
+ public function testWorkerRecordsWhatItIsWorkingOn()
+ {
+ $worker = new Resque_Worker('jobs');
+ $worker->setLogger(new Resque_Log());
+ $worker->registerWorker();
+
+ $payload = [
+ 'class' => 'Test_Job'
+ ];
+ $job = new Resque_Job('jobs', $payload);
+ $worker->workingOn($job);
+
+ $job = $worker->job();
+ $this->assertEquals('jobs', $job['queue']);
+ if (!isset($job['run_at'])) {
+ $this->fail('Job does not have run_at time');
+ }
+ $this->assertEquals($payload, $job['payload']);
+ }
+
+ public function testWorkerErasesItsStatsWhenShutdown()
+ {
+ Resque::enqueue('jobs', 'Test_Job');
+ Resque::enqueue('jobs', 'Invalid_Job');
+
+ $worker = new Resque_Worker('jobs');
+ $worker->setLogger(new Resque_Log());
+ $worker->work(0);
+ $worker->work(0);
+
+ $this->assertEquals(0, $worker->getStat('processed'));
+ $this->assertEquals(0, $worker->getStat('failed'));
+ }
+
+ public function testWorkerCleansUpDeadWorkersOnStartup()
+ {
+ // Register a good worker
+ $goodWorker = new Resque_Worker('jobs');
+ $goodWorker->setLogger(new Resque_Log());
+ $goodWorker->registerWorker();
+ $workerId = explode(':', $goodWorker);
+
+ // Register some bad workers
+ $worker = new Resque_Worker('jobs');
+ $worker->setLogger(new Resque_Log());
+ $worker->setId($workerId[0] . ':1:jobs');
+ $worker->registerWorker();
+
+ $worker = new Resque_Worker(['high', 'low']);
+ $worker->setLogger(new Resque_Log());
+ $worker->setId($workerId[0] . ':2:high,low');
+ $worker->registerWorker();
+
+ $this->assertEquals(3, count(Resque_Worker::all()));
+
+ $goodWorker->pruneDeadWorkers();
+
+ // There should only be $goodWorker left now
+ $this->assertEquals(1, count(Resque_Worker::all()));
+ }
+
+ public function testDeadWorkerCleanUpDoesNotCleanUnknownWorkers()
+ {
+ // Register a bad worker on this machine
+ $worker = new Resque_Worker('jobs');
+ $worker->setLogger(new Resque_Log());
+ $workerId = explode(':', $worker);
+ $worker->setId($workerId[0] . ':1:jobs');
+ $worker->registerWorker();
+
+ // Register some other false workers
+ $worker = new Resque_Worker('jobs');
+ $worker->setLogger(new Resque_Log());
+ $worker->setId('my.other.host:1:jobs');
+ $worker->registerWorker();
+
+ $this->assertEquals(2, count(Resque_Worker::all()));
+
+ $worker->pruneDeadWorkers();
+
+ // my.other.host should be left
+ $workers = Resque_Worker::all();
+ $this->assertEquals(1, count($workers));
+ $this->assertEquals((string)$worker, (string)$workers[0]);
+ }
+
+ public function testWorkerFailsUncompletedJobsOnExit()
+ {
+ $worker = new Resque_Worker('jobs');
+ $worker->setLogger(new Resque_Log());
+ $worker->registerWorker();
+
+ $payload = [
+ 'class' => 'Test_Job'
+ ];
+ $job = new Resque_Job('jobs', $payload);
+
+ $worker->workingOn($job);
+ $worker->unregisterWorker();
+
+ $this->assertEquals(1, Resque_Stat::get('failed'));
+ }
public function testBlockingListPop()
{
$worker = new Resque_Worker('jobs');
- $worker->setLogger(new Resque_Log());
+ $worker->setLogger(new Resque_Log());
$worker->registerWorker();
Resque::enqueue('jobs', 'Test_Job_1');
Resque::enqueue('jobs', 'Test_Job_2');
$i = 1;
- while($job = $worker->reserve(true, 1))
- {
+ while ($job = $worker->reserve(true, 1)) {
$this->assertEquals('Test_Job_' . $i, $job->payload['class']);
- if($i == 2) {
+ if ($i == 2) {
break;
}
diff --git a/test/bootstrap.php b/test/bootstrap.php
index a4b68377..a92611c2 100644
--- a/test/bootstrap.php
+++ b/test/bootstrap.php
@@ -2,9 +2,9 @@
/**
* Resque test bootstrap file - sets up a test environment.
*
- * @package Resque/Tests
- * @author Chris Boulton
- * @license http://www.opensource.org/licenses/mit-license.php
+ * @package Resque/Tests
+ * @author Chris Boulton
+ * @license http://www.opensource.org/licenses/mit-license.php
*/
$loader = require __DIR__ . '/../vendor/autoload.php';
@@ -15,24 +15,24 @@
// Attempt to start our own redis instance for tesitng.
exec('which redis-server', $output, $returnVar);
-if($returnVar != 0) {
- echo "Cannot find redis-server in path. Please make sure redis is installed.\n";
- exit(1);
+if ($returnVar != 0) {
+ 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);
+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);
+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]);
@@ -43,57 +43,59 @@ 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);
-
- if(is_file($pidFile)) {
- unlink($pidFile);
- }
- }
-
- // Remove the redis database
- if(!preg_match('#^\s*dir\s+([^\s]+)#m', $config, $matches)) {
- return;
- }
- $dir = $matches[1];
-
- if(!preg_match('#^\s*dbfilename\s+([^\s]+)#m', $config, $matches)) {
- return;
- }
-
- $filename = TEST_MISC . '/' . $dir . '/' . $matches[1];
- if(is_file($filename)) {
- unlink($filename);
- }
+ $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);
+
+ if (is_file($pidFile)) {
+ unlink($pidFile);
+ }
+ }
+
+ // Remove the redis database
+ if (!preg_match('#^\s*dir\s+([^\s]+)#m', $config, $matches)) {
+ return;
+ }
+ $dir = $matches[1];
+
+ if (!preg_match('#^\s*dbfilename\s+([^\s]+)#m', $config, $matches)) {
+ return;
+ }
+
+ $filename = TEST_MISC . '/' . $dir . '/' . $matches[1];
+ if (is_file($filename)) {
+ unlink($filename);
+ }
}
+
register_shutdown_function('killRedis', getmypid());
-if(function_exists('pcntl_signal')) {
- // Override INT and TERM signals, so they do a clean shutdown and also
- // clean up redis-server as well.
- function sigint()
- {
- exit;
- }
- pcntl_signal(SIGINT, 'sigint');
- pcntl_signal(SIGTERM, 'sigint');
+if (function_exists('pcntl_signal')) {
+ // Override INT and TERM signals, so they do a clean shutdown and also
+ // clean up redis-server as well.
+ function sigint()
+ {
+ exit;
+ }
+
+ pcntl_signal(SIGINT, 'sigint');
+ pcntl_signal(SIGTERM, 'sigint');
}
class Test_Job
{
- public static $called = false;
+ public static $called = false;
- public function perform()
- {
- self::$called = true;
- }
+ public function perform()
+ {
+ self::$called = true;
+ }
}
class Failing_Job_Exception extends Exception
@@ -103,10 +105,10 @@ class Failing_Job_Exception extends Exception
class Failing_Job
{
- public function perform()
- {
- throw new Failing_Job_Exception('Message!');
- }
+ public function perform()
+ {
+ throw new Failing_Job_Exception('Message!');
+ }
}
class Test_Job_Without_Perform_Method
@@ -116,33 +118,33 @@ class Test_Job_Without_Perform_Method
class Test_Job_With_SetUp
{
- public static $called = false;
- public $args = false;
+ public static $called = false;
+ public $args = false;
- public function setUp()
- {
- self::$called = true;
- }
+ public function setUp()
+ {
+ self::$called = true;
+ }
- public function perform()
- {
+ public function perform()
+ {
- }
+ }
}
class Test_Job_With_TearDown
{
- public static $called = false;
- public $args = false;
+ public static $called = false;
+ public $args = false;
- public function perform()
- {
+ public function perform()
+ {
- }
+ }
- public function tearDown()
- {
- self::$called = true;
- }
+ public function tearDown()
+ {
+ self::$called = true;
+ }
}
\ No newline at end of file