Skip to content

Commit

Permalink
Merge pull request #134 from clue-labs/default-loop
Browse files Browse the repository at this point in the history
Simplify usage by supporting new default loop
  • Loading branch information
WyriHaximus authored Jul 17, 2021
2 parents f4f680a + 75c4e4f commit 8bed9ef
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 48 deletions.
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ It is written in pure PHP and does not require any extensions.
This example runs a simple `SELECT` query and dumps all the records from a `book` table:

```php
$loop = React\EventLoop\Factory::create();
$factory = new Factory($loop);
$factory = new React\MySQL\Factory();

$uri = 'test:test@localhost/test';
$connection = $factory->createLazyConnection($uri);
Expand All @@ -51,8 +50,6 @@ $connection->query('SELECT * FROM book')->then(
);

$connection->quit();

$loop->run();
```

See also the [examples](examples).
Expand All @@ -62,19 +59,23 @@ See also the [examples](examples).
### Factory

The `Factory` is responsible for creating your [`ConnectionInterface`](#connectioninterface) instance.
It also registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage).

```php
$loop = \React\EventLoop\Factory::create();
$factory = new Factory($loop);
$factory = new React\MySQL\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 connector settings (DNS resolution, TLS parameters, timeouts,
proxy servers etc.), 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'
Expand All @@ -85,7 +86,7 @@ $connector = new \React\Socket\Connector($loop, array(
)
));

$factory = new Factory($loop, $connector);
$factory = new React\MySQL\Factory(null, $connector);
```

#### createConnection()
Expand Down Expand Up @@ -120,7 +121,7 @@ connection attempt and/or MySQL authentication.
```php
$promise = $factory->createConnection($url);

$loop->addTimer(3.0, function () use ($promise) {
Loop::addTimer(3.0, function () use ($promise) {
$promise->cancel();
});
```
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"require": {
"php": ">=5.4.0",
"evenement/evenement": "^3.0 || ^2.1 || ^1.1",
"react/event-loop": "^1.0 || ^0.5",
"react/event-loop": "^1.2",
"react/promise": "^2.7",
"react/promise-stream": "^1.1",
"react/promise-timer": "^1.5",
"react/socket": "^1.1"
"react/socket": "^1.8"
},
"require-dev": {
"clue/block-react": "^1.2",
Expand Down
5 changes: 1 addition & 4 deletions examples/01-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

require __DIR__ . '/../vendor/autoload.php';

$loop = React\EventLoop\Factory::create();
$factory = new Factory($loop);
$factory = new Factory();

$uri = 'test:test@localhost/test';
$query = isset($argv[1]) ? $argv[1] : 'select * from book';
Expand All @@ -33,5 +32,3 @@
});

$connection->quit();

$loop->run();
5 changes: 1 addition & 4 deletions examples/02-query-stream.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

require __DIR__ . '/../vendor/autoload.php';

$loop = React\EventLoop\Factory::create();
$factory = new Factory($loop);
$factory = new Factory();

$uri = 'test:test@localhost/test';
$query = isset($argv[1]) ? $argv[1] : 'select * from book';
Expand All @@ -30,5 +29,3 @@
});

$connection->quit();

$loop->run();
7 changes: 2 additions & 5 deletions examples/11-interactive.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@

require __DIR__ . '/../vendor/autoload.php';

$loop = React\EventLoop\Factory::create();
$factory = new Factory($loop);
$factory = new Factory();

$uri = 'test:test@localhost/test';

// open a STDIN stream to read keyboard input (not supported on Windows)
$stdin = new ReadableResourceStream(STDIN, $loop);
$stdin = new ReadableResourceStream(STDIN);
$stdin->pause();

//create a mysql connection for executing queries
Expand Down Expand Up @@ -86,5 +85,3 @@
echo 'Connection error: ' . $e->getMessage() . PHP_EOL;
$stdin->close();
});

$loop->run();
16 changes: 7 additions & 9 deletions examples/12-slow-stream.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

// $ php examples/12-slow-stream.php "SHOW VARIABLES"

use React\EventLoop\Loop;
use React\MySQL\ConnectionInterface;
use React\MySQL\Factory;

require __DIR__ . '/../vendor/autoload.php';

$loop = React\EventLoop\Factory::create();
$factory = new Factory($loop);
$factory = new Factory();

$uri = 'test:test@localhost/test';
$query = isset($argv[1]) ? $argv[1] : 'select * from book';

//create a mysql connection for executing query
$factory->createConnection($uri)->then(function (ConnectionInterface $connection) use ($query, $loop) {
$factory->createConnection($uri)->then(function (ConnectionInterface $connection) use ($query) {
// The protocol parser reads rather large chunked from the underlying connection
// and as such can yield multiple (dozens to hundreds) rows from a single data
// chunk. We try to artifically limit the stream chunk size here to try to
Expand Down Expand Up @@ -44,13 +44,13 @@
$stream = $connection->queryStream($query);

$throttle = null;
$stream->on('data', function ($row) use ($loop, &$throttle, $stream) {
$stream->on('data', function ($row) use (&$throttle, $stream) {
echo json_encode($row, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;

// simple throttle mechanism: explicitly pause the result stream and
// resume it again after some time.
if ($throttle === null) {
$throttle = $loop->addTimer(1.0, function () use ($stream, &$throttle) {
$throttle = Loop::addTimer(1.0, function () use ($stream, &$throttle) {
$throttle = null;
$stream->resume();
});
Expand All @@ -62,16 +62,14 @@
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});

$stream->on('close', function () use ($loop, &$throttle) {
$stream->on('close', function () use (&$throttle) {
echo 'CLOSED' . PHP_EOL;

if ($throttle) {
$loop->cancelTimer($throttle);
Loop::cancelTimer($throttle);
$throttle = null;
}
});

$connection->quit();
}, 'printf');

$loop->run();
32 changes: 18 additions & 14 deletions src/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace React\MySQL;

use React\EventLoop\Loop;
use React\EventLoop\LoopInterface;
use React\MySQL\Commands\AuthenticateCommand;
use React\MySQL\Io\Connection;
Expand All @@ -17,24 +18,31 @@

class Factory
{
/** @var LoopInterface */
private $loop;

/** @var ConnectorInterface */
private $connector;

/**
* The `Factory` is responsible for creating your [`ConnectionInterface`](#connectioninterface) instance.
* It also registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage).
*
* ```php
* $loop = \React\EventLoop\Factory::create();
* $factory = new Factory($loop);
* $factory = new React\MySQL\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 connector settings (DNS resolution, TLS parameters, timeouts,
* proxy servers etc.), 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'
Expand All @@ -45,20 +53,16 @@ class Factory
* )
* ));
*
* $factory = new Factory($loop, $connector);
* $factory = new React\MySQL\Factory(null, $connector);
* ```
*
* @param LoopInterface $loop
* @param ConnectorInterface|null $connector
* @param ?LoopInterface $loop
* @param ?ConnectorInterface $connector
*/
public function __construct(LoopInterface $loop, ConnectorInterface $connector = null)
public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null)
{
if ($connector === null) {
$connector = new Connector($loop);
}

$this->loop = $loop;
$this->connector = $connector;
$this->loop = $loop ?: Loop::get();
$this->connector = $connector ?: new Connector($this->loop);
}

/**
Expand Down
11 changes: 11 additions & 0 deletions tests/FactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@

class FactoryTest extends BaseTestCase
{
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 testConnectWillUseHostAndDefaultPort()
{
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
Expand Down

0 comments on commit 8bed9ef

Please sign in to comment.