From 1b59378eeb9c65a5b436e47c0c90259f08237951 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 14 Apr 2021 19:13:44 +0200 Subject: [PATCH] User global loop accessor --- composer.json | 10 +++++-- examples/cli.php | 16 +++++------ examples/incr.php | 6 ++-- examples/publish.php | 6 ++-- examples/subscribe.php | 14 ++++----- src/Factory.php | 12 ++++---- src/LazyClient.php | 18 ++++++------ tests/FactoryLazyClientTest.php | 13 ++++++++- tests/FactoryStreamingClientTest.php | 14 +++++++-- tests/FunctionalTest.php | 43 +++++++++++++++++----------- tests/LazyClientTest.php | 12 +++++++- 11 files changed, 103 insertions(+), 61 deletions(-) diff --git a/composer.json b/composer.json index 3a12889..af558c8 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "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": "dev-global-event-loop-accessor-part-four as 1.2.0", "react/promise": "^2.0 || ^1.1", "react/promise-timer": "^1.5", "react/socket": "^1.1" @@ -28,5 +28,11 @@ }, "autoload-dev": { "psr-4": { "Clue\\Tests\\React\\Redis\\": "tests/" } - } + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/wyrihaximus-labs/event-loop" + } + ] } diff --git a/examples/cli.php b/examples/cli.php index f4dd537..5ac9d48 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::get()->addReadStream(STDIN, function () use ($client) { $line = fgets(STDIN); if ($line === false || $line === '') { echo '# CTRL-D -> Ending connection...' . PHP_EOL; - $loop->removeReadStream(STDIN); + Loop::get()->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::get()->removeReadStream(STDIN); }); }, function (Exception $error) { echo 'CONNECTION ERROR: ' . $error->getMessage() . PHP_EOL; @@ -56,4 +56,4 @@ exit(1); }); -$loop->run(); +Loop::get()->run(); diff --git a/examples/incr.php b/examples/incr.php index 0eaaa32..0034d87 100644 --- a/examples/incr.php +++ b/examples/incr.php @@ -1,11 +1,11 @@ createLazyClient('localhost'); $client->incr('test'); @@ -22,4 +22,4 @@ $client->end(); -$loop->run(); +Loop::get()->run(); diff --git a/examples/publish.php b/examples/publish.php index 4da3c17..f7f98e5 100644 --- a/examples/publish.php +++ b/examples/publish.php @@ -1,11 +1,11 @@ end(); -$loop->run(); +Loop::get()->run(); diff --git a/examples/subscribe.php b/examples/subscribe.php index 3dedae8..a8fe218 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::get()->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::get()->cancelTimer($timer); }, function (Exception $e) { echo 'Unable to subscribe again: ' . $e->getMessage() . PHP_EOL; }); }); }); -$loop->run(); +Loop::get()->run(); diff --git a/src/Factory.php b/src/Factory.php index ce95c41..d5d63f8 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,27 +14,24 @@ class Factory { - private $loop; private $connector; 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 */ - public function __construct(LoopInterface $loop, ConnectorInterface $connector = null, ProtocolFactory $protocol = null) + public function __construct(ConnectorInterface $connector = null, ProtocolFactory $protocol = null) { if ($connector === null) { - $connector = new Connector($loop); + $connector = new Connector(Loop::get()); } if ($protocol === null) { $protocol = new ProtocolFactory(); } - $this->loop = $loop; $this->connector = $connector; $this->protocol = $protocol; } @@ -121,7 +119,7 @@ function ($error) use ($client) { return $deferred->promise(); } - return \React\Promise\Timer\timeout($deferred->promise(), $timeout, $this->loop)->then(null, function ($e) { + return \React\Promise\Timer\timeout($deferred->promise(), $timeout, Loop::get())->then(null, function ($e) { if ($e instanceof TimeoutException) { throw new \RuntimeException( 'Connection to Redis server timed out after ' . $e->getTimeout() . ' seconds' @@ -139,7 +137,7 @@ function ($error) use ($client) { */ public function createLazyClient($target) { - return new LazyClient($target, $this, $this->loop); + return new LazyClient($target, $this); } /** diff --git a/src/LazyClient.php b/src/LazyClient.php index bfb2fef..2e19051 100644 --- a/src/LazyClient.php +++ b/src/LazyClient.php @@ -3,6 +3,7 @@ namespace Clue\React\Redis; use Evenement\EventEmitter; +use React\EventLoop\Loop; use React\Stream\Util; use React\EventLoop\LoopInterface; @@ -17,7 +18,6 @@ class LazyClient extends EventEmitter implements Client private $closed = false; private $promise; - private $loop; private $idlePeriod = 60.0; private $idleTimer; private $pending = 0; @@ -28,7 +28,7 @@ class LazyClient extends EventEmitter implements Client /** * @param $target */ - public function __construct($target, Factory $factory, LoopInterface $loop) + public function __construct($target, Factory $factory) { $args = array(); \parse_str(\parse_url($target, \PHP_URL_QUERY), $args); @@ -38,7 +38,6 @@ public function __construct($target, Factory $factory, LoopInterface $loop) $this->target = $target; $this->factory = $factory; - $this->loop = $loop; } private function client() @@ -52,10 +51,9 @@ private function client() $idleTimer=& $this->idleTimer; $subscribed =& $this->subscribed; $psubscribed =& $this->psubscribed; - $loop = $this->loop; - return $pending = $this->factory->createClient($this->target)->then(function (Client $client) use ($self, &$pending, &$idleTimer, &$subscribed, &$psubscribed, $loop) { + return $pending = $this->factory->createClient($this->target)->then(function (Client $client) use ($self, &$pending, &$idleTimer, &$subscribed, &$psubscribed) { // connection completed => remember only until closed - $client->on('close', function () use (&$pending, $self, &$subscribed, &$psubscribed, &$idleTimer, $loop) { + $client->on('close', function () use (&$pending, $self, &$subscribed, &$psubscribed, &$idleTimer) { $pending = null; // foward unsubscribe/punsubscribe events when underlying connection closes @@ -71,7 +69,7 @@ private function client() $psubscribed = array(); if ($idleTimer !== null) { - $loop->cancelTimer($idleTimer); + Loop::get()->cancelTimer($idleTimer); $idleTimer = null; } }); @@ -173,7 +171,7 @@ public function close() } if ($this->idleTimer !== null) { - $this->loop->cancelTimer($this->idleTimer); + Loop::get()->cancelTimer($this->idleTimer); $this->idleTimer = null; } @@ -189,7 +187,7 @@ public function awake() ++$this->pending; if ($this->idleTimer !== null) { - $this->loop->cancelTimer($this->idleTimer); + Loop::get()->cancelTimer($this->idleTimer); $this->idleTimer = null; } } @@ -204,7 +202,7 @@ public function idle() if ($this->pending < 1 && $this->idlePeriod >= 0 && !$this->subscribed && !$this->psubscribed && $this->promise !== null) { $idleTimer =& $this->idleTimer; $promise =& $this->promise; - $idleTimer = $this->loop->addTimer($this->idlePeriod, function () use (&$idleTimer, &$promise) { + $idleTimer = Loop::get()->addTimer($this->idlePeriod, function () use (&$idleTimer, &$promise) { $promise->then(function (Client $client) { $client->close(); }); diff --git a/tests/FactoryLazyClientTest.php b/tests/FactoryLazyClientTest.php index c0a6430..681bfc3 100644 --- a/tests/FactoryLazyClientTest.php +++ b/tests/FactoryLazyClientTest.php @@ -3,6 +3,7 @@ namespace Clue\Tests\React\Redis; use Clue\React\Redis\Factory; +use React\EventLoop\Loop; use React\Promise; class FactoryLazyClientTest extends TestCase @@ -17,8 +18,18 @@ class FactoryLazyClientTest extends TestCase public function setUpFactory() { $this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->loop); $this->connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); - $this->factory = new Factory($this->loop, $this->connector); + $this->factory = new Factory($this->connector); + } + + + /** + * @after + */ + public function resetLoop() + { + Loop::reset(); } public function testWillConnectWithDefaultPort() diff --git a/tests/FactoryStreamingClientTest.php b/tests/FactoryStreamingClientTest.php index 2c577a1..19b3cc8 100644 --- a/tests/FactoryStreamingClientTest.php +++ b/tests/FactoryStreamingClientTest.php @@ -3,6 +3,7 @@ namespace Clue\Tests\React\Redis; use Clue\React\Redis\Factory; +use React\EventLoop\Loop; use React\Promise; use React\Promise\Deferred; @@ -18,8 +19,17 @@ class FactoryStreamingClientTest extends TestCase public function setUpFactory() { $this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->loop); $this->connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); - $this->factory = new Factory($this->loop, $this->connector); + $this->factory = new Factory($this->connector); + } + + /** + * @after + */ + public function resetLoop() + { + Loop::reset(); } /** @@ -27,7 +37,7 @@ public function setUpFactory() */ public function testCtor() { - $this->factory = new Factory($this->loop); + $this->factory = new Factory(); } public function testWillConnectWithDefaultPort() diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index 7e70b71..06ed2b5 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -6,13 +6,13 @@ use Clue\React\Redis\Client; use Clue\React\Redis\Factory; use Clue\React\Redis\StreamingClient; +use React\EventLoop\Loop; use React\EventLoop\StreamSelectLoop; use React\Promise\Deferred; use React\Stream\DuplexResourceStream; class FunctionalTest extends TestCase { - private $loop; private $factory; private $uri; @@ -26,8 +26,17 @@ public function setUpFactory() $this->markTestSkipped('No REDIS_URI environment variable given'); } - $this->loop = new StreamSelectLoop(); - $this->factory = new Factory($this->loop); + Loop::set(new StreamSelectLoop()); + $this->factory = new Factory(); + } + + + /** + * @after + */ + public function resetLoop() + { + Loop::reset(); } public function testPing() @@ -37,7 +46,7 @@ public function testPing() $promise = $client->ping(); $this->assertInstanceOf('React\Promise\PromiseInterface', $promise); - $ret = Block\await($promise, $this->loop); + $ret = Block\await($promise, Loop::get()); $this->assertEquals('PONG', $ret); } @@ -49,7 +58,7 @@ public function testPingLazy() $promise = $client->ping(); $this->assertInstanceOf('React\Promise\PromiseInterface', $promise); - $ret = Block\await($promise, $this->loop); + $ret = Block\await($promise, Loop::get()); $this->assertEquals('PONG', $ret); } @@ -63,7 +72,7 @@ public function testPingLazyWillNotBlockLoopWhenIdleTimeIsSmall() $client->ping(); - $this->loop->run(); + Loop::get()->run(); } /** @@ -73,7 +82,7 @@ public function testLazyClientWithoutCommandsWillNotBlockLoop() { $client = $this->factory->createLazyClient($this->uri); - $this->loop->run(); + Loop::get()->run(); unset($client); } @@ -87,7 +96,7 @@ public function testMgetIsNotInterpretedAsSubMessage() $promise = $client->mget('message', 'channel', 'payload')->then($this->expectCallableOnce()); $client->on('message', $this->expectCallableNever()); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testPipeline() @@ -99,7 +108,7 @@ public function testPipeline() $client->incr('a')->then($this->expectCallableOnceWith(3)); $promise = $client->get('a')->then($this->expectCallableOnceWith('3')); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testInvalidCommand() @@ -112,7 +121,7 @@ public function testInvalidCommand() } else { $this->setExpectedException('Exception'); } - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testMultiExecEmpty() @@ -121,7 +130,7 @@ public function testMultiExecEmpty() $client->multi()->then($this->expectCallableOnceWith('OK')); $promise = $client->exec()->then($this->expectCallableOnceWith(array())); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testMultiExecQueuedExecHasValues() @@ -135,7 +144,7 @@ public function testMultiExecQueuedExecHasValues() $client->ttl('b')->then($this->expectCallableOnceWith('QUEUED')); $promise = $client->exec()->then($this->expectCallableOnceWith(array('OK', 1, 12, 20))); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testPubSub() @@ -156,7 +165,7 @@ public function testPubSub() })->then($this->expectCallableOnce()); // expect "message" event to take no longer than 0.1s - Block\await($deferred->promise(), $this->loop, 0.1); + Block\await($deferred->promise(), Loop::get(), 0.1); } public function testClose() @@ -195,7 +204,7 @@ public function testInvalidProtocol() } else { $this->setExpectedException('Exception'); } - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testInvalidServerRepliesWithDuplicateMessages() @@ -207,7 +216,7 @@ public function testInvalidServerRepliesWithDuplicateMessages() $promise = $client->set('a', 0)->then($this->expectCallableOnceWith('OK')); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } /** @@ -216,7 +225,7 @@ public function testInvalidServerRepliesWithDuplicateMessages() */ protected function createClient($uri) { - return Block\await($this->factory->createClient($uri), $this->loop); + return Block\await($this->factory->createClient($uri), Loop::get()); } protected function createClientResponse($response) @@ -225,7 +234,7 @@ protected function createClientResponse($response) fwrite($fp, $response); fseek($fp, 0); - $stream = new DuplexResourceStream($fp, $this->loop); + $stream = new DuplexResourceStream($fp, Loop::get()); return new StreamingClient($stream); } diff --git a/tests/LazyClientTest.php b/tests/LazyClientTest.php index 1faf779..96c9bd9 100644 --- a/tests/LazyClientTest.php +++ b/tests/LazyClientTest.php @@ -11,6 +11,7 @@ use Clue\Redis\Protocol\Model\MultiBulkReply; use Clue\React\Redis\Client; use React\EventLoop\Factory; +use React\EventLoop\Loop; use React\Stream\ThroughStream; use React\Promise\Promise; use React\Promise\Deferred; @@ -28,8 +29,17 @@ public function setUpClient() { $this->factory = $this->getMockBuilder('Clue\React\Redis\Factory')->disableOriginalConstructor()->getMock(); $this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->loop); - $this->client = new LazyClient('localhost', $this->factory, $this->loop); + $this->client = new LazyClient('localhost', $this->factory); + } + + /** + * @after + */ + public function resetLoop() + { + Loop::reset(); } public function testPingWillCreateUnderlyingClientAndReturnPendingPromise()