Skip to content

Commit 0e8ed06

Browse files
committed
Simplify API, add new RedisClient and remove Factory
1 parent 1e34a7a commit 0e8ed06

14 files changed

+232
-588
lines changed

README.md

+57-177
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,8 @@ It enables you to set and query its data or use its PubSub topics to react to in
4242
* [Promises](#promises)
4343
* [PubSub](#pubsub)
4444
* [API](#api)
45-
* [Factory](#factory)
46-
* [createClient()](#createclient)
47-
* [createLazyClient()](#createlazyclient)
48-
* [Client](#client)
45+
* [RedisClient](#redisclient)
46+
* [__construct()](#__construct)
4947
* [__call()](#__call)
5048
* [end()](#end)
5149
* [close()](#close)
@@ -75,8 +73,7 @@ local Redis server and send some requests:
7573

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

78-
$factory = new Clue\React\Redis\Factory();
79-
$redis = $factory->createLazyClient('localhost:6379');
76+
$redis = new Clue\React\Redis\RedisClient('localhost:6379');
8077

8178
$redis->set('greeting', 'Hello world');
8279
$redis->append('greeting', '!');
@@ -100,10 +97,12 @@ See also the [examples](examples).
10097

10198
### Commands
10299

103-
Most importantly, this project provides a [`Client`](#client) instance that
100+
Most importantly, this project provides a [`RedisClient`](#redisclient) instance that
104101
can be used to invoke all [Redis commands](https://redis.io/commands) (such as `GET`, `SET`, etc.).
105102

106103
```php
104+
$redis = new Clue\React\Redis\RedisClient('localhost:6379');
105+
107106
$redis->get($key);
108107
$redis->set($key, $value);
109108
$redis->exists($key);
@@ -262,161 +261,28 @@ $redis->on('punsubscribe', function (string $pattern, int $total) {
262261
});
263262
```
264263

265-
When using the [`createLazyClient()`](#createlazyclient) method, the `unsubscribe`
266-
and `punsubscribe` events will be invoked automatically when the underlying
267-
connection is lost. This gives you control over re-subscribing to the channels
268-
and patterns as appropriate.
264+
When the underlying connection is lost, the `unsubscribe` and `punsubscribe` events
265+
will be invoked automatically. This gives you control over re-subscribing to the
266+
channels and patterns as appropriate.
269267

270268
## API
271269

272-
### Factory
273-
274-
The `Factory` is responsible for creating your [`Client`](#client) instance.
275-
276-
```php
277-
$factory = new Clue\React\Redis\Factory();
278-
```
279-
280-
This class takes an optional `LoopInterface|null $loop` parameter that can be used to
281-
pass the event loop instance to use for this object. You can use a `null` value
282-
here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
283-
This value SHOULD NOT be given unless you're sure you want to explicitly use a
284-
given event loop instance.
285-
286-
If you need custom connector settings (DNS resolution, TLS parameters, timeouts,
287-
proxy servers etc.), you can explicitly pass a custom instance of the
288-
[`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface):
289-
290-
```php
291-
$connector = new React\Socket\Connector([
292-
'dns' => '127.0.0.1',
293-
'tcp' => [
294-
'bindto' => '192.168.10.1:0'
295-
],
296-
'tls' => [
297-
'verify_peer' => false,
298-
'verify_peer_name' => false
299-
]
300-
]);
301-
302-
$factory = new Clue\React\Redis\Factory(null, $connector);
303-
```
304-
305-
#### createClient()
306-
307-
The `createClient(string $uri): PromiseInterface<Client,Exception>` method can be used to
308-
create a new [`Client`](#client).
270+
### RedisClient
309271

310-
It helps with establishing a plain TCP/IP or secure TLS connection to Redis
311-
and optionally authenticating (AUTH) and selecting the right database (SELECT).
312-
313-
```php
314-
$factory->createClient('localhost:6379')->then(
315-
function (Client $redis) {
316-
// client connected (and authenticated)
317-
},
318-
function (Exception $e) {
319-
// an error occurred while trying to connect (or authenticate) client
320-
}
321-
);
322-
```
323-
324-
The method returns a [Promise](https://github.com/reactphp/promise) that
325-
will resolve with a [`Client`](#client)
326-
instance on success or will reject with an `Exception` if the URL is
327-
invalid or the connection or authentication fails.
328-
329-
The returned Promise is implemented in such a way that it can be
330-
cancelled when it is still pending. Cancelling a pending promise will
331-
reject its value with an Exception and will cancel the underlying TCP/IP
332-
connection attempt and/or Redis authentication.
333-
334-
```php
335-
$promise = $factory->createClient($uri);
336-
337-
Loop::addTimer(3.0, function () use ($promise) {
338-
$promise->cancel();
339-
});
340-
```
341-
342-
The `$redisUri` can be given in the
343-
[standard](https://www.iana.org/assignments/uri-schemes/prov/redis) form
344-
`[redis[s]://][:auth@]host[:port][/db]`.
345-
You can omit the URI scheme and port if you're connecting to the default port 6379:
346-
347-
```php
348-
// both are equivalent due to defaults being applied
349-
$factory->createClient('localhost');
350-
$factory->createClient('redis://localhost:6379');
351-
```
352-
353-
Redis supports password-based authentication (`AUTH` command). Note that Redis'
354-
authentication mechanism does not employ a username, so you can pass the
355-
password `h@llo` URL-encoded (percent-encoded) as part of the URI like this:
356-
357-
```php
358-
// all forms are equivalent
359-
$factory->createClient('redis://:h%40llo@localhost');
360-
$factory->createClient('redis://ignored:h%40llo@localhost');
361-
$factory->createClient('redis://localhost?password=h%40llo');
362-
```
363-
364-
You can optionally include a path that will be used to select (SELECT command) the right database:
365-
366-
```php
367-
// both forms are equivalent
368-
$factory->createClient('redis://localhost/2');
369-
$factory->createClient('redis://localhost?db=2');
370-
```
371-
372-
You can use the [standard](https://www.iana.org/assignments/uri-schemes/prov/rediss)
373-
`rediss://` URI scheme if you're using a secure TLS proxy in front of Redis:
374-
375-
```php
376-
$factory->createClient('rediss://redis.example.com:6340');
377-
```
378-
379-
You can use the `redis+unix://` URI scheme if your Redis instance is listening
380-
on a Unix domain socket (UDS) path:
381-
382-
```php
383-
$factory->createClient('redis+unix:///tmp/redis.sock');
384-
385-
// the URI MAY contain `password` and `db` query parameters as seen above
386-
$factory->createClient('redis+unix:///tmp/redis.sock?password=secret&db=2');
387-
388-
// the URI MAY contain authentication details as userinfo as seen above
389-
// should be used with care, also note that database can not be passed as path
390-
$factory->createClient('redis+unix://:secret@/tmp/redis.sock');
391-
```
392-
393-
This method respects PHP's `default_socket_timeout` setting (default 60s)
394-
as a timeout for establishing the connection and waiting for successful
395-
authentication. You can explicitly pass a custom timeout value in seconds
396-
(or use a negative number to not apply a timeout) like this:
397-
398-
```php
399-
$factory->createClient('localhost?timeout=0.5');
400-
```
401-
402-
#### createLazyClient()
403-
404-
The `createLazyClient(string $uri): Client` method can be used to
405-
create a new [`Client`](#client).
406-
407-
It helps with establishing a plain TCP/IP or secure TLS connection to Redis
408-
and optionally authenticating (AUTH) and selecting the right database (SELECT).
272+
The `RedisClient` is responsible for exchanging messages with your Redis server
273+
and keeps track of pending commands.
409274

410275
```php
411-
$redis = $factory->createLazyClient('localhost:6379');
276+
$redis = new Clue\React\Redis\RedisClient('localhost:6379');
412277

413278
$redis->incr('hello');
414279
$redis->end();
415280
```
416281

417-
This method immediately returns a "virtual" connection implementing the
418-
[`Client`](#client) that can be used to interface with your Redis database.
419-
Internally, it lazily creates the underlying database connection only on
282+
Besides defining a few methods, this interface also implements the
283+
`EventEmitterInterface` which allows you to react to certain events as documented below.
284+
285+
Internally, this class creates the underlying database connection only on
420286
demand once the first request is invoked on this instance and will queue
421287
all outstanding requests until the underlying connection is ready.
422288
Additionally, it will only keep this underlying connection in an "idle" state
@@ -428,9 +294,6 @@ database right away while the underlying connection may still be
428294
outstanding. Because creating this underlying connection may take some
429295
time, it will enqueue all oustanding commands and will ensure that all
430296
commands will be executed in correct order once the connection is ready.
431-
In other words, this "virtual" connection behaves just like a "real"
432-
connection as described in the `Client` interface and frees you from having
433-
to deal with its async resolution.
434297

435298
If the underlying database connection fails, it will reject all
436299
outstanding commands and will return to the initial "idle" state. This
@@ -450,24 +313,25 @@ creating a new underlying connection repeating the above commands again.
450313
Note that creating the underlying connection will be deferred until the
451314
first request is invoked. Accordingly, any eventual connection issues
452315
will be detected once this instance is first used. You can use the
453-
`end()` method to ensure that the "virtual" connection will be soft-closed
316+
`end()` method to ensure that the connection will be soft-closed
454317
and no further commands can be enqueued. Similarly, calling `end()` on
455318
this instance when not currently connected will succeed immediately and
456319
will not have to wait for an actual underlying connection.
457320

458-
Depending on your particular use case, you may prefer this method or the
459-
underlying `createClient()` which resolves with a promise. For many
460-
simple use cases it may be easier to create a lazy connection.
321+
#### __construct()
322+
323+
The `new RedisClient(string $url, ConnectorInterface $connector = null, LoopInterface $loop = null)` constructor can be used to
324+
create a new `RedisClient` instance.
461325

462-
The `$redisUri` can be given in the
326+
The `$url` can be given in the
463327
[standard](https://www.iana.org/assignments/uri-schemes/prov/redis) form
464328
`[redis[s]://][:auth@]host[:port][/db]`.
465329
You can omit the URI scheme and port if you're connecting to the default port 6379:
466330

467331
```php
468332
// both are equivalent due to defaults being applied
469-
$factory->createLazyClient('localhost');
470-
$factory->createLazyClient('redis://localhost:6379');
333+
$redis = new Clue\React\Redis\RedisClient('localhost');
334+
$redis = new Clue\React\Redis\RedisClient('redis://localhost:6379');
471335
```
472336

473337
Redis supports password-based authentication (`AUTH` command). Note that Redis'
@@ -476,38 +340,38 @@ password `h@llo` URL-encoded (percent-encoded) as part of the URI like this:
476340

477341
```php
478342
// all forms are equivalent
479-
$factory->createLazyClient('redis://:h%40llo@localhost');
480-
$factory->createLazyClient('redis://ignored:h%40llo@localhost');
481-
$factory->createLazyClient('redis://localhost?password=h%40llo');
343+
$redis = new Clue\React\Redis\RedisClient('redis://:h%40llo@localhost');
344+
$redis = new Clue\React\Redis\RedisClient('redis://ignored:h%40llo@localhost');
345+
$redis = new Clue\React\Redis\RedisClient('redis://localhost?password=h%40llo');
482346
```
483347

484348
You can optionally include a path that will be used to select (SELECT command) the right database:
485349

486350
```php
487351
// both forms are equivalent
488-
$factory->createLazyClient('redis://localhost/2');
489-
$factory->createLazyClient('redis://localhost?db=2');
352+
$redis = new Clue\React\Redis\RedisClient('redis://localhost/2');
353+
$redis = new Clue\React\Redis\RedisClient('redis://localhost?db=2');
490354
```
491355

492356
You can use the [standard](https://www.iana.org/assignments/uri-schemes/prov/rediss)
493357
`rediss://` URI scheme if you're using a secure TLS proxy in front of Redis:
494358

495359
```php
496-
$factory->createLazyClient('rediss://redis.example.com:6340');
360+
$redis = new Clue\React\Redis\RedisClient('rediss://redis.example.com:6340');
497361
```
498362

499363
You can use the `redis+unix://` URI scheme if your Redis instance is listening
500364
on a Unix domain socket (UDS) path:
501365

502366
```php
503-
$factory->createLazyClient('redis+unix:///tmp/redis.sock');
367+
$redis = new Clue\React\Redis\RedisClient('redis+unix:///tmp/redis.sock');
504368

505369
// the URI MAY contain `password` and `db` query parameters as seen above
506-
$factory->createLazyClient('redis+unix:///tmp/redis.sock?password=secret&db=2');
370+
$redis = new Clue\React\Redis\RedisClient('redis+unix:///tmp/redis.sock?password=secret&db=2');
507371

508372
// the URI MAY contain authentication details as userinfo as seen above
509373
// should be used with care, also note that database can not be passed as path
510-
$factory->createLazyClient('redis+unix://:secret@/tmp/redis.sock');
374+
$redis = new Clue\React\Redis\RedisClient('redis+unix://:secret@/tmp/redis.sock');
511375
```
512376

513377
This method respects PHP's `default_socket_timeout` setting (default 60s)
@@ -516,7 +380,7 @@ successful authentication. You can explicitly pass a custom timeout value
516380
in seconds (or use a negative number to not apply a timeout) like this:
517381

518382
```php
519-
$factory->createLazyClient('localhost?timeout=0.5');
383+
$redis = new Clue\React\Redis\RedisClient('localhost?timeout=0.5');
520384
```
521385

522386
By default, this method will keep "idle" connections open for 60s and will
@@ -529,16 +393,32 @@ idle timeout value in seconds (or use a negative number to not apply a
529393
timeout) like this:
530394

531395
```php
532-
$factory->createLazyClient('localhost?idle=0.1');
396+
$redis = new Clue\React\Redis\RedisClient('localhost?idle=0.1');
533397
```
534398

535-
### Client
399+
If you need custom DNS, proxy or TLS settings, you can explicitly pass a
400+
custom instance of the [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface):
536401

537-
The `Client` is responsible for exchanging messages with Redis
538-
and keeps track of pending commands.
402+
```php
403+
$connector = new React\Socket\Connector([
404+
'dns' => '127.0.0.1',
405+
'tcp' => [
406+
'bindto' => '192.168.10.1:0'
407+
],
408+
'tls' => [
409+
'verify_peer' => false,
410+
'verify_peer_name' => false
411+
]
412+
]);
539413

540-
Besides defining a few methods, this interface also implements the
541-
`EventEmitterInterface` which allows you to react to certain events as documented below.
414+
$redis = new Clue\React\Redis\RedisClient('localhost', $connector);
415+
```
416+
417+
This class takes an optional `LoopInterface|null $loop` parameter that can be used to
418+
pass the event loop instance to use for this object. You can use a `null` value
419+
here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
420+
This value SHOULD NOT be given unless you're sure you want to explicitly use a
421+
given event loop instance.
542422

543423
#### __call()
544424

0 commit comments

Comments
 (0)