mirror of
https://github.com/idanoo/php-resque.git
synced 2024-11-22 00:11:53 +00:00
Merge branch 'master' of github.com:chrisboulton/php-resque
This commit is contained in:
commit
1517d45904
@ -30,7 +30,15 @@ if(empty($QUEUE)) {
|
|||||||
die("Set QUEUE env var containing the list of queues to work.\n");
|
die("Set QUEUE env var containing the list of queues to work.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REDIS_BACKEND can have simple 'host:port' format or use a DSN-style format like this:
|
||||||
|
* - redis://user:pass@host:port
|
||||||
|
*
|
||||||
|
* Note: the 'user' part of the DSN URI is required but is not used.
|
||||||
|
*/
|
||||||
$REDIS_BACKEND = getenv('REDIS_BACKEND');
|
$REDIS_BACKEND = getenv('REDIS_BACKEND');
|
||||||
|
|
||||||
|
// A redis database number
|
||||||
$REDIS_BACKEND_DB = getenv('REDIS_BACKEND_DB');
|
$REDIS_BACKEND_DB = getenv('REDIS_BACKEND_DB');
|
||||||
if(!empty($REDIS_BACKEND)) {
|
if(!empty($REDIS_BACKEND)) {
|
||||||
if (empty($REDIS_BACKEND_DB))
|
if (empty($REDIS_BACKEND_DB))
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.0",
|
"php": ">=5.3.0",
|
||||||
"ext-pcntl": "*",
|
"ext-pcntl": "*",
|
||||||
"colinmollenhour/credis": "1.2.*",
|
"colinmollenhour/credis": "~1.2",
|
||||||
"psr/log": "1.0.0"
|
"psr/log": "1.0.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
@ -7,6 +7,9 @@ require __DIR__ . '/init.php';
|
|||||||
|
|
||||||
date_default_timezone_set('GMT');
|
date_default_timezone_set('GMT');
|
||||||
Resque::setBackend('127.0.0.1:6379');
|
Resque::setBackend('127.0.0.1:6379');
|
||||||
|
// You can also use a DSN-style format:
|
||||||
|
//Resque::setBackend('redis://user:pass@127.0.0.1:6379');
|
||||||
|
//Resque::setBackend('redis://user:pass@a.host.name:3432/2');
|
||||||
|
|
||||||
$status = new Resque_Job_Status($argv[1]);
|
$status = new Resque_Job_Status($argv[1]);
|
||||||
if(!$status->isTracking()) {
|
if(!$status->isTracking()) {
|
||||||
|
@ -7,6 +7,10 @@ require __DIR__ . '/init.php';
|
|||||||
date_default_timezone_set('GMT');
|
date_default_timezone_set('GMT');
|
||||||
Resque::setBackend('127.0.0.1:6379');
|
Resque::setBackend('127.0.0.1:6379');
|
||||||
|
|
||||||
|
// You can also use a DSN-style format:
|
||||||
|
//Resque::setBackend('redis://user:pass@127.0.0.1:6379');
|
||||||
|
//Resque::setBackend('redis://user:pass@a.host.name:3432/2');
|
||||||
|
|
||||||
$args = array(
|
$args = array(
|
||||||
'time' => time(),
|
'time' => time(),
|
||||||
'array' => array(
|
'array' => array(
|
||||||
|
@ -32,7 +32,7 @@ class Resque
|
|||||||
* Given a host/port combination separated by a colon, set it as
|
* Given a host/port combination separated by a colon, set it as
|
||||||
* the redis server that Resque will talk to.
|
* the redis server that Resque will talk to.
|
||||||
*
|
*
|
||||||
* @param mixed $server Host/port combination separated by a colon, or
|
* @param mixed $server Host/port combination separated by a colon, DSN-formatted URI, or
|
||||||
* a nested array of servers with host/port pairs.
|
* a nested array of servers with host/port pairs.
|
||||||
* @param int $database
|
* @param int $database
|
||||||
*/
|
*/
|
||||||
@ -54,12 +54,7 @@ class Resque
|
|||||||
return self::$redis;
|
return self::$redis;
|
||||||
}
|
}
|
||||||
|
|
||||||
$server = self::$redisServer;
|
self::$redis = new Resque_Redis(self::$redisServer, self::$redisDatabase);
|
||||||
if (empty($server)) {
|
|
||||||
$server = 'localhost:6379';
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$redis = new Resque_Redis($server, self::$redisDatabase);
|
|
||||||
return self::$redis;
|
return self::$redis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,14 +8,26 @@
|
|||||||
*/
|
*/
|
||||||
class Resque_Redis
|
class Resque_Redis
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Redis namespace
|
* Redis namespace
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $defaultNamespace = 'resque:';
|
private static $defaultNamespace = 'resque:';
|
||||||
|
|
||||||
private $server;
|
/**
|
||||||
private $database;
|
* A default host to connect to
|
||||||
|
*/
|
||||||
|
const DEFAULT_HOST = 'localhost';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default Redis port
|
||||||
|
*/
|
||||||
|
const DEFAULT_PORT = 6379;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default Redis Database number
|
||||||
|
*/
|
||||||
|
const DEFAULT_DATABASE = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array List of all commands in Redis that supply a key as their
|
* @var array List of all commands in Redis that supply a key as their
|
||||||
@ -92,47 +104,106 @@ class Resque_Redis
|
|||||||
self::$defaultNamespace = $namespace;
|
self::$defaultNamespace = $namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct($server, $database = null)
|
/**
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
public function __construct($server, $database = null)
|
||||||
{
|
{
|
||||||
$this->server = $server;
|
if (is_array($server)) {
|
||||||
$this->database = $database;
|
|
||||||
|
|
||||||
if (is_array($this->server)) {
|
|
||||||
$this->driver = new Credis_Cluster($server);
|
$this->driver = new Credis_Cluster($server);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$port = null;
|
|
||||||
$password = null;
|
|
||||||
$host = $server;
|
|
||||||
|
|
||||||
// If not a UNIX socket path or tcp:// formatted connections string
|
list($host, $port, $dsnDatabase, $user, $password, $options) = self::parseDsn($server);
|
||||||
// assume host:port combination.
|
// $user is not used, only $password
|
||||||
if (strpos($server, '/') === false) {
|
|
||||||
$parts = explode(':', $server);
|
// Look for known Credis_Client options
|
||||||
if (isset($parts[1])) {
|
$timeout = isset($options['timeout']) ? intval($options['timeout']) : null;
|
||||||
$port = $parts[1];
|
$persistent = isset($options['persistent']) ? $options['persistent'] : '';
|
||||||
}
|
|
||||||
$host = $parts[0];
|
$this->driver = new Credis_Client($host, $port, $timeout, $persistent);
|
||||||
}else if (strpos($server, 'redis://') !== false){
|
if ($password){
|
||||||
// Redis format is:
|
|
||||||
// redis://[user]:[password]@[host]:[port]
|
|
||||||
list($userpwd,$hostport) = explode('@', $server);
|
|
||||||
$userpwd = substr($userpwd, strpos($userpwd, 'redis://')+8);
|
|
||||||
list($host, $port) = explode(':', $hostport);
|
|
||||||
list($user, $password) = explode(':', $userpwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->driver = new Credis_Client($host, $port);
|
|
||||||
if (isset($password)){
|
|
||||||
$this->driver->auth($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 ($this->database !== null) {
|
if ($database !== null) {
|
||||||
$this->driver->select($database);
|
$this->driver->select($database);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
$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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$parts['host'],
|
||||||
|
$port,
|
||||||
|
$database,
|
||||||
|
$user,
|
||||||
|
$pass,
|
||||||
|
$options,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magic method to handle all function requests and prefix key based
|
* Magic method to handle all function requests and prefix key based
|
||||||
* operations with the {self::$defaultNamespace} key prefix.
|
* operations with the {self::$defaultNamespace} key prefix.
|
||||||
@ -141,37 +212,38 @@ class Resque_Redis
|
|||||||
* @param array $args Array of supplied arguments to the method.
|
* @param array $args Array of supplied arguments to the method.
|
||||||
* @return mixed Return value from Resident::call() based on the command.
|
* @return mixed Return value from Resident::call() based on the command.
|
||||||
*/
|
*/
|
||||||
public function __call($name, $args) {
|
public function __call($name, $args)
|
||||||
if(in_array($name, $this->keyCommands)) {
|
{
|
||||||
if(is_array($args[0])) {
|
if (in_array($name, $this->keyCommands)) {
|
||||||
foreach($args[0] AS $i => $v) {
|
if (is_array($args[0])) {
|
||||||
$args[0][$i] = self::$defaultNamespace . $v;
|
foreach ($args[0] AS $i => $v) {
|
||||||
}
|
$args[0][$i] = self::$defaultNamespace . $v;
|
||||||
} else {
|
}
|
||||||
$args[0] = self::$defaultNamespace . $args[0];
|
}
|
||||||
}
|
else {
|
||||||
|
$args[0] = self::$defaultNamespace . $args[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return $this->driver->__call($name, $args);
|
return $this->driver->__call($name, $args);
|
||||||
}
|
}
|
||||||
catch(CredisException $e) {
|
catch (CredisException $e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getPrefix()
|
public static function getPrefix()
|
||||||
{
|
{
|
||||||
return self::$defaultNamespace;
|
return self::$defaultNamespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function removePrefix($string)
|
public static function removePrefix($string)
|
||||||
{
|
{
|
||||||
$prefix=self::getPrefix();
|
$prefix=self::getPrefix();
|
||||||
|
|
||||||
if (substr($string, 0, strlen($prefix)) == $prefix) {
|
if (substr($string, 0, strlen($prefix)) == $prefix) {
|
||||||
$string = substr($string, strlen($prefix), strlen($string) );
|
$string = substr($string, strlen($prefix), strlen($string) );
|
||||||
}
|
}
|
||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
|
182
test/Resque/Tests/DsnTest.php
Normal file
182
test/Resque/Tests/DsnTest.php
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Resque_Redis DSN tests.
|
||||||
|
*
|
||||||
|
* @package Resque/Tests
|
||||||
|
* @author Iskandar Najmuddin <github@iskandar.co.uk>
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php
|
||||||
|
*/
|
||||||
|
class Resque_Tests_DsnTest extends Resque_Tests_TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user