Skip to content

Commit

Permalink
Deprecate options array, use URI query string instead, add connect ti…
Browse files Browse the repository at this point in the history
…meout option

Resolves #32.
  • Loading branch information
kelunik committed Apr 29, 2016
1 parent ad0d030 commit 8c4f71f
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 63 deletions.
75 changes: 54 additions & 21 deletions lib/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Amp\Deferred;
use Amp\Promise;
use Amp\Promisor;
use DomainException;
use Exception;
use function Amp\all;
use function Amp\pipe;
Expand All @@ -17,19 +16,40 @@ class Client extends Redis {
/** @var Connection */
private $connection;
/** @var string */
private $uri;
/** @var string */
private $password;
/** @var int */
private $database;
private $database = 0;

/**
* @param string $uri
* @param array $options
* @param array|null $options
*/
public function __construct($uri, array $options = []) {
$this->applyOptions($options);
public function __construct($uri, array $options = null) {
if (is_array($options) || func_num_args() === 2) {
trigger_error(
"Using the options array is deprecated and will be removed in the next version. " .
"Please use the URI to pass options like that: tcp://localhost:6379?database=3&password=abc",
E_USER_DEPRECATED
);

$options = $options ?: [];

if (isset($options["password"])) {
$this->password = $options["password"];
}

if (isset($options["database"])) {
$this->database = (int) $options["database"];
}
}

$this->applyUri($uri);

$this->promisors = [];
$this->connection = new Connection($this->uri);

$this->connection = new Connection($uri);
$this->connection->addEventHandler("response", function ($response) {
$promisor = array_shift($this->promisors);

Expand All @@ -50,7 +70,7 @@ public function __construct($uri, array $options = []) {
}
});

if ($this->database != 0) {
if ($this->database !== 0) {
$this->connection->addEventHandler("connect", function () {
// SELECT must be called for every new connection if another database than 0 is used
array_unshift($this->promisors, new Deferred);
Expand All @@ -61,31 +81,44 @@ public function __construct($uri, array $options = []) {

if (!empty($this->password)) {
$this->connection->addEventHandler("connect", function () {
// AUTH must be before any other command, so we unshift it here
// AUTH must be before any other command, so we unshift it last
array_unshift($this->promisors, new Deferred);

return "*2\r\n$4\r\rAUTH\r\n$" . strlen($this->password) . "\r\n{$this->password}\r\n";
});
}
}

private function applyOptions(array $options) {
$this->password = isset($options["password"]) ? $options["password"] : null;
private function applyUri($uri) {
$parts = explode("?", $uri, 2);
$this->uri = $parts[0];

if (!is_string($this->password) && !is_null($this->password)) {
throw new DomainException(sprintf(
"Password must be string or null, %s given",
gettype($this->password)
));
if (count($parts) === 1) {
return;
}

$this->database = isset($options["database"]) ? $options["database"] : 0;
$query = $parts[1];
$params = explode("&", $query);

if (!is_int($this->database)) {
throw new DomainException(sprintf(
"Database must be int, %s given",
gettype($this->database)
));
foreach ($params as $param) {
$keyValue = explode("=", $param, 2);
$key = urldecode($keyValue[0]);

if (count($keyValue) === 1) {
$value = true;
} else {
$value = urldecode($keyValue[1]);
}

switch ($key) {
case "database":
$this->database = (int) $value;
break;

case "password":
$this->password = $value;
break;
}
}
}

Expand Down
37 changes: 35 additions & 2 deletions lib/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class Connection {

/** @var string */
private $uri;
/** @var int */
private $timeout = 1000;
/** @var resource */
private $socket;
/** @var string */
Expand Down Expand Up @@ -61,7 +63,8 @@ public function __construct($uri) {
throw new DomainException("URI must start with tcp:// or unix://");
}

$this->uri = $uri;
$this->parseUri($uri);

$this->outputBufferLength = 0;
$this->outputBuffer = "";
$this->state = self::STATE_DISCONNECTED;
Expand All @@ -80,6 +83,36 @@ public function __construct($uri) {
});
}

private function parseUri($uri) {
$parts = explode("?", $uri, 2);

if (count($parts) === 1) {
$this->uri = $uri;

return;
}

$query = $parts[1];
$params = explode("&", $query);

foreach ($params as $param) {
$keyValue = explode("=", $param, 2);
$key = $keyValue[0];

if (count($keyValue) === 1) {
$value = true;
} else {
$value = $keyValue[0];
}

switch ($key) {
case "timeout":
$this->timeout = (int) $value;
break;
}
}
}

public function addEventHandler($event, callable $callback) {
$events = (array) $event;

Expand Down Expand Up @@ -134,7 +167,7 @@ private function connect() {

$this->state = self::STATE_CONNECTING;
$this->connectPromisor = new Deferred;
$socketPromise = connect($this->uri, ["timeout" => 1000]);
$socketPromise = connect($this->uri, ["timeout" => $this->timeout]);

$onWrite = function ($watcherId) {
if ($this->outputBufferLength === 0) {
Expand Down
64 changes: 52 additions & 12 deletions lib/SubscribeClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,36 @@ class SubscribeClient {
private $patternPromisors;
/** @var Connection */
private $connection;
/** @var string */
private $uri;
/** @var string */
private $password;

/**
* @param string $uri
* @param array $options
*/
public function __construct($uri, $options = []) {
$password = isset($options["password"]) ? $options["password"] : null;

if (!is_string($password) && !is_null($password)) {
throw new DomainException(sprintf(
"Password must be string or null, %s given",
gettype($password)
));
public function __construct($uri, array $options = null) {
if (is_array($options) || func_num_args() === 2) {
trigger_error(
"Using the options array is deprecated and will be removed in the next version. " .
"Please use the URI to pass options like that: tcp://localhost:6379?database=3&password=abc",
E_USER_DEPRECATED
);

$options = $options ?: [];

if (isset($options["password"])) {
$this->password = $options["password"];
}
}

$this->applyUri($uri);

$this->promisors = [];
$this->patternPromisors = [];

$this->connection = new Connection($uri);
$this->connection = new Connection($this->uri);
$this->connection->addEventHandler("response", function ($response) {
if ($this->authPromisor) {
if ($response instanceof Exception) {
Expand Down Expand Up @@ -115,16 +126,45 @@ public function __construct($uri, $options = []) {
}
});

if (!empty($password)) {
$this->connection->addEventHandler("connect", function () use ($password) {
if (!empty($this->password)) {
$this->connection->addEventHandler("connect", function () {
// AUTH must be before any other command, so we unshift it here
$this->authPromisor = new Deferred;

return "*2\r\n$4\r\rAUTH\r\n$" . strlen($password) . "\r\n{$password}\r\n";
return "*2\r\n$4\r\rAUTH\r\n$" . strlen($this->password) . "\r\n{$this->password}\r\n";
});
}
}

private function applyUri($uri) {
$parts = explode("?", $uri, 2);
$this->uri = $parts[0];

if (count($parts) === 1) {
return;
}

$query = $parts[1];
$params = explode("&", $query);

foreach ($params as $param) {
$keyValue = explode("=", $param, 2);
$key = urldecode($keyValue[0]);

if (count($keyValue) === 1) {
$value = true;
} else {
$value = urldecode($keyValue[1]);
}

switch ($key) {
case "password":
$this->password = $value;
break;
}
}
}

/**
* @return Promise
*/
Expand Down
2 changes: 1 addition & 1 deletion test/AuthTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static function tearDownAfterClass() {
*/
function ping() {
reactor(driver())->run(function () {
$redis = new Client("tcp://127.0.0.1:25325", ["password" => "secret"]);
$redis = new Client("tcp://127.0.0.1:25325?password=secret");
$this->assertEquals("PONG", (yield $redis->ping()));
$redis->close();
});
Expand Down
16 changes: 5 additions & 11 deletions test/BasicTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ class BasicTest extends RedisTest {
*/
function connect() {
reactor(driver())->run(function () {
$redis = new Client("tcp://127.0.0.1:25325", []);
$redis = new Client("tcp://127.0.0.1:25325");
$this->assertEquals("PONG", (yield $redis->ping()));
$redis->close();
});
}

Expand All @@ -24,11 +23,10 @@ function connect() {
*/
function longPayload() {
reactor(driver())->run(function () {
$redis = new Client("tcp://127.0.0.1:25325", []);
$redis = new Client("tcp://127.0.0.1:25325");
$payload = str_repeat("a", 6000000);
yield $redis->set("foobar", $payload);
$this->assertEquals($payload, (yield $redis->get("foobar")));
$redis->close();
});
}

Expand All @@ -38,7 +36,7 @@ function longPayload() {
*/
function acceptsOnlyScalars() {
reactor(driver())->run(function () {
$redis = new Client("tcp://127.0.0.1:25325", []);
$redis = new Client("tcp://127.0.0.1:25325");
$redis->set("foobar", ["abc"]);
});
}
Expand All @@ -48,10 +46,9 @@ function acceptsOnlyScalars() {
*/
function multiCommand() {
reactor(driver())->run(function () {
$redis = new Client("tcp://127.0.0.1:25325", []);
$redis = new Client("tcp://127.0.0.1:25325");
$redis->echo("1");
$this->assertEquals("2", (yield $redis->echo("2")));
$redis->close();
});
}

Expand All @@ -61,13 +58,10 @@ function multiCommand() {
*/
function timeout() {
reactor(driver())->run(function () {
$redis = new Client("tcp://127.0.0.1:25325", []);
$redis = new Client("tcp://127.0.0.1:25325");
yield $redis->echo("1");

yield new Pause(8000);

$this->assertEquals("2", (yield $redis->echo("2")));
$redis->close();
});
}
}
2 changes: 1 addition & 1 deletion test/CloseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class CloseTest extends RedisTest {
*/
function reconnect() {
reactor(driver())->run(function () {
$redis = new Client("tcp://127.0.0.1:25325", []);
$redis = new Client("tcp://127.0.0.1:25325");
$this->assertEquals("PONG", (yield $redis->ping()));
yield $redis->close();
$this->assertEquals("PONG", (yield $redis->ping()));
Expand Down
2 changes: 1 addition & 1 deletion test/DownTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class DownTest extends \PHPUnit_Framework_TestCase {
*/
function ping() {
reactor(driver())->run(function () {
$redis = new Client("tcp://127.0.0.1:25325", []);
$redis = new Client("tcp://127.0.0.1:25325");
yield $redis->ping();
});
}
Expand Down
Loading

0 comments on commit 8c4f71f

Please sign in to comment.