From bd94553d4c1e3d7e1c16f39d443f6533f4d9c42b Mon Sep 17 00:00:00 2001 From: Simon Frings Date: Wed, 28 Jul 2021 13:15:27 +0200 Subject: [PATCH] Simplify usage by supporting new default loop --- README.md | 23 +++++++++++----------- composer.json | 4 ++-- examples/cli.php | 16 +++++++-------- examples/incr.php | 5 +---- examples/publish.php | 5 +---- examples/subscribe.php | 14 ++++++-------- src/Factory.php | 29 +++++++++++++--------------- tests/FactoryLazyClientTest.php | 11 +++++++++++ tests/FactoryStreamingClientTest.php | 11 +++++++++++ 9 files changed, 64 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 5f81659..0cc11c8 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,7 @@ Once [installed](#install), you can use the following code to connect to your local Redis server and send some requests: ```php -$loop = React\EventLoop\Factory::create(); -$factory = new Clue\React\Redis\Factory($loop); +$factory = new Clue\React\Redis\Factory(); $client = $factory->createLazyClient('localhost'); $client->set('greeting', 'Hello world'); @@ -78,8 +77,6 @@ $client->incr('invocation')->then(function ($n) { // end connection once all pending requests have been resolved $client->end(); - -$loop->run(); ``` See also the [examples](examples). @@ -89,18 +86,22 @@ See also the [examples](examples). ### Factory The `Factory` is responsible for creating your [`Client`](#client) instance. -It also registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage). ```php -$loop = \React\EventLoop\Factory::create(); -$factory = new \Clue\React\Redis\Factory($loop); +$factory = new Clue\React\Redis\Factory(); ``` +This class takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use for this object. You can use a `null` value +here in order to use the [default loop](https://github.com/reactphp/event-loop#loop). +This value SHOULD NOT be given unless you're sure you want to explicitly use a +given event loop instance. + If you need custom DNS, proxy or TLS settings, you can explicitly pass a custom instance of the [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface): ```php -$connector = new \React\Socket\Connector($loop, array( +$connector = new React\Socket\Connector(null, array( 'dns' => '127.0.0.1', 'tcp' => array( 'bindto' => '192.168.10.1:0' @@ -111,7 +112,7 @@ $connector = new \React\Socket\Connector($loop, array( ) )); -$factory = new Factory($loop, $connector); +$factory = new Clue\React\Redis\Factory(null, $connector); ``` #### createClient() @@ -146,7 +147,7 @@ connection attempt and/or Redis authentication. ```php $promise = $factory->createClient($redisUri); -$loop->addTimer(3.0, function () use ($promise) { +Loop::addTimer(3.0, function () use ($promise) { $promise->cancel(); }); ``` @@ -466,7 +467,7 @@ respectively: ```php $client->subscribe('user'); -$loop->addTimer(60.0, function () use ($client) { +Loop::addTimer(60.0, function () use ($client) { $client->unsubscribe('user'); }); ``` diff --git a/composer.json b/composer.json index 3a12889..8f4dde6 100644 --- a/composer.json +++ b/composer.json @@ -14,10 +14,10 @@ "php": ">=5.3", "clue/redis-protocol": "0.3.*", "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "react/event-loop": "^1.0 || ^0.5", + "react/event-loop": "^1.2", "react/promise": "^2.0 || ^1.1", "react/promise-timer": "^1.5", - "react/socket": "^1.1" + "react/socket": "^1.8" }, "require-dev": { "clue/block-react": "^1.1", diff --git a/examples/cli.php b/examples/cli.php index f4dd537..8f2baed 100644 --- a/examples/cli.php +++ b/examples/cli.php @@ -2,23 +2,23 @@ use Clue\React\Redis\Client; use Clue\React\Redis\Factory; +use React\EventLoop\Loop; use React\Promise\PromiseInterface; require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$factory = new Factory($loop); +$factory = new Factory(); echo '# connecting to redis...' . PHP_EOL; -$factory->createClient('localhost')->then(function (Client $client) use ($loop) { +$factory->createClient('localhost')->then(function (Client $client) { echo '# connected! Entering interactive mode, hit CTRL-D to quit' . PHP_EOL; - $loop->addReadStream(STDIN, function () use ($client, $loop) { + Loop::addReadStream(STDIN, function () use ($client) { $line = fgets(STDIN); if ($line === false || $line === '') { echo '# CTRL-D -> Ending connection...' . PHP_EOL; - $loop->removeReadStream(STDIN); + Loop::removeReadStream(STDIN); return $client->end(); } @@ -43,10 +43,10 @@ }); }); - $client->on('close', function() use ($loop) { + $client->on('close', function() { echo '## DISCONNECTED' . PHP_EOL; - $loop->removeReadStream(STDIN); + Loop::removeReadStream(STDIN); }); }, function (Exception $error) { echo 'CONNECTION ERROR: ' . $error->getMessage() . PHP_EOL; @@ -55,5 +55,3 @@ } exit(1); }); - -$loop->run(); diff --git a/examples/incr.php b/examples/incr.php index 0eaaa32..8eb34e9 100644 --- a/examples/incr.php +++ b/examples/incr.php @@ -4,8 +4,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$factory = new Factory($loop); +$factory = new Factory(); $client = $factory->createLazyClient('localhost'); $client->incr('test'); @@ -21,5 +20,3 @@ }); $client->end(); - -$loop->run(); diff --git a/examples/publish.php b/examples/publish.php index 4da3c17..8f371e0 100644 --- a/examples/publish.php +++ b/examples/publish.php @@ -4,8 +4,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$factory = new Factory($loop); +$factory = new Factory(); $channel = isset($argv[1]) ? $argv[1] : 'channel'; $message = isset($argv[2]) ? $argv[2] : 'message'; @@ -22,5 +21,3 @@ }); $client->end(); - -$loop->run(); diff --git a/examples/subscribe.php b/examples/subscribe.php index 3dedae8..bb22a67 100644 --- a/examples/subscribe.php +++ b/examples/subscribe.php @@ -1,11 +1,11 @@ on('unsubscribe', function ($channel) use ($client, $loop) { +$client->on('unsubscribe', function ($channel) use ($client) { echo 'Unsubscribed from ' . $channel . PHP_EOL; - $loop->addPeriodicTimer(2.0, function ($timer) use ($client, $channel, $loop){ - $client->subscribe($channel)->then(function () use ($timer, $loop) { + Loop::addPeriodicTimer(2.0, function ($timer) use ($client, $channel){ + $client->subscribe($channel)->then(function () use ($timer) { echo 'Now subscribed again' . PHP_EOL; - $loop->cancelTimer($timer); + Loop::cancelTimer($timer); }, function (Exception $e) { echo 'Unable to subscribe again: ' . $e->getMessage() . PHP_EOL; }); }); }); - -$loop->run(); diff --git a/src/Factory.php b/src/Factory.php index ce95c41..aec03da 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -3,6 +3,7 @@ namespace Clue\React\Redis; use Clue\Redis\Protocol\Factory as ProtocolFactory; +use React\EventLoop\Loop; use React\EventLoop\LoopInterface; use React\Promise\Deferred; use React\Promise\Timer\TimeoutException; @@ -13,29 +14,25 @@ class Factory { + /** @var LoopInterface */ private $loop; + + /** @var ConnectorInterface */ private $connector; + + /** @var ProtocolFactory */ private $protocol; /** - * @param LoopInterface $loop - * @param ConnectorInterface|null $connector [optional] Connector to use. - * Should be `null` in order to use default Connector. - * @param ProtocolFactory|null $protocol + * @param ?LoopInterface $loop + * @param ?ConnectorInterface $connector + * @param ?ProtocolFactory $protocol */ - public function __construct(LoopInterface $loop, ConnectorInterface $connector = null, ProtocolFactory $protocol = null) + public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null, ProtocolFactory $protocol = null) { - if ($connector === null) { - $connector = new Connector($loop); - } - - if ($protocol === null) { - $protocol = new ProtocolFactory(); - } - - $this->loop = $loop; - $this->connector = $connector; - $this->protocol = $protocol; + $this->loop = $loop ?: Loop::get(); + $this->connector = $connector ?: new Connector($this->loop); + $this->protocol = $protocol ?: new ProtocolFactory(); } /** diff --git a/tests/FactoryLazyClientTest.php b/tests/FactoryLazyClientTest.php index c0a6430..33a216c 100644 --- a/tests/FactoryLazyClientTest.php +++ b/tests/FactoryLazyClientTest.php @@ -21,6 +21,17 @@ public function setUpFactory() $this->factory = new Factory($this->loop, $this->connector); } + public function testConstructWithoutLoopAssignsLoopAutomatically() + { + $factory = new Factory(); + + $ref = new \ReflectionProperty($factory, 'loop'); + $ref->setAccessible(true); + $loop = $ref->getValue($factory); + + $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); + } + public function testWillConnectWithDefaultPort() { $this->connector->expects($this->never())->method('connect')->with('redis.example.com:6379')->willReturn(Promise\reject(new \RuntimeException())); diff --git a/tests/FactoryStreamingClientTest.php b/tests/FactoryStreamingClientTest.php index 2c577a1..bb43f66 100644 --- a/tests/FactoryStreamingClientTest.php +++ b/tests/FactoryStreamingClientTest.php @@ -22,6 +22,17 @@ public function setUpFactory() $this->factory = new Factory($this->loop, $this->connector); } + public function testConstructWithoutLoopAssignsLoopAutomatically() + { + $factory = new Factory(); + + $ref = new \ReflectionProperty($factory, 'loop'); + $ref->setAccessible(true); + $loop = $ref->getValue($factory); + + $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); + } + /** * @doesNotPerformAssertions */