Skip to content

Commit

Permalink
Merge pull request #27 from SimonFrings/naming
Browse files Browse the repository at this point in the history
Improve documentation and examples
  • Loading branch information
clue authored May 9, 2022
2 parents 327b2f9 + 9c23823 commit 5869138
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 47 deletions.
62 changes: 31 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# clue/reactphp-ndjson

[![CI status](https://github.com/clue/reactphp-ndjson/workflows/CI/badge.svg)](https://github.com/clue/reactphp-ndjson/actions)
[![CI status](https://github.com/clue/reactphp-ndjson/actions/workflows/ci.yml/badge.svg)](https://github.com/clue/reactphp-ndjson/actions)
[![installs on Packagist](https://img.shields.io/packagist/dt/clue/ndjson-react?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/clue/ndjson-react)

Streaming newline-delimited JSON ([NDJSON](http://ndjson.org/)) parser and encoder for [ReactPHP](https://reactphp.org/).
Expand All @@ -10,7 +10,7 @@ file to store any kind of (uniform) structured data, such as a list of user
objects or log entries. It uses a simple newline character between each
individual record and as such can be both used for efficient persistence and
simple append-style operations. This also allows it to be used in a streaming
context, such as a simple inter-process commmunication (IPC) protocol or for a
context, such as a simple inter-process communication (IPC) protocol or for a
remote procedure call (RPC) mechanism. This library provides a simple
streaming API to process very large NDJSON files with thousands or even millions
of rows efficiently without having to load the whole file into memory at once.
Expand Down Expand Up @@ -39,7 +39,7 @@ of rows efficiently without having to load the whole file into memory at once.

## Support us

We invest a lot of time developing, maintaining and updating our awesome
We invest a lot of time developing, maintaining, and updating our awesome
open-source projects. You can help us sustain this high-quality of our work by
[becoming a sponsor on GitHub](https://github.com/sponsors/clue). Sponsors get
numerous benefits in return, see our [sponsoring page](https://github.com/sponsors/clue)
Expand Down Expand Up @@ -75,7 +75,7 @@ no "outer array" to be modified). This makes it a perfect fit for a streaming
context, for line-oriented CLI tools (such as `grep` and others) or for a logging
context where you want to append records at a later time. Additionally, this
also allows it to be used in a streaming context, such as a simple inter-process
commmunication (IPC) protocol or for a remote procedure call (RPC) mechanism.
communication (IPC) protocol or for a remote procedure call (RPC) mechanism.

The newline character at the end of each line allows for some really simple
*framing* (detecting individual records). While each individual line is valid
Expand Down Expand Up @@ -134,12 +134,12 @@ as parsed values instead of just chunks of strings:
```

```php
$stdin = new ReadableResourceStream(STDIN);
$stdin = new React\Stream\ReadableResourceStream(STDIN);

$stream = new Decoder($stdin);
$ndjson = new Clue\React\NDJson\Decoder($stdin);

$stream->on('data', function ($data) {
// data is a parsed element from the JSON stream
$ndjson->on('data', function ($data) {
// $data is a parsed element from the JSON stream
// line 1: $data = (object)array('name' => 'test', 'active' => true);
// line 2: $data = (object)array('name' => 'hello wörld', 'active' => true);
var_dump($data);
Expand All @@ -157,9 +157,9 @@ This means that, by default, JSON objects will be emitted as a `stdClass`.
This behavior can be controlled through the optional constructor parameters:

```php
$stream = new Decoder($stdin, true);
$ndjson = new Clue\React\NDJson\Decoder($stdin, true);

$stream->on('data', function ($data) {
$ndjson->on('data', function ($data) {
// JSON objects will be emitted as assoc arrays now
});
```
Expand All @@ -171,15 +171,15 @@ unreasonably long lines. It accepts an additional argument if you want to change
this from the default of 64 KiB:

```php
$stream = new Decoder($stdin, false, 512, 0, 64 * 1024);
$ndjson = new Clue\React\NDJson\Decoder($stdin, false, 512, 0, 64 * 1024);
```

If the underlying stream emits an `error` event or the plain stream contains
any data that does not represent a valid NDJson stream,
it will emit an `error` event and then `close` the input stream:

```php
$stream->on('error', function (Exception $error) {
$ndjson->on('error', function (Exception $error) {
// an error occured, stream will close next
});
```
Expand All @@ -190,7 +190,7 @@ followed by an `end` event on success or an `error` event for
incomplete/invalid JSON data as above:

```php
$stream->on('end', function () {
$ndjson->on('end', function () {
// stream successfully ended, stream will close next
});
```
Expand All @@ -199,7 +199,7 @@ If either the underlying stream or the `Decoder` is closed, it will forward
the `close` event:

```php
$stream->on('close', function () {
$ndjson->on('close', function () {
// stream closed
// possibly after an "end" event or due to an "error" event
});
Expand All @@ -209,7 +209,7 @@ The `close(): void` method can be used to explicitly close the `Decoder` and
its underlying stream:

```php
$stream->close();
$ndjson->close();
```

The `pipe(WritableStreamInterface $dest, array $options = array(): WritableStreamInterface`
Expand All @@ -218,7 +218,7 @@ Please note that the `Decoder` emits decoded/parsed data events, while many
(most?) writable streams expect only data chunks:

```php
$stream->pipe($logger);
$ndjson->pipe($logger);
```

For more details, see ReactPHP's
Expand All @@ -234,12 +234,12 @@ and accepts its data through the same interface, but handles any data as complet
JSON elements instead of just chunks of strings:

```php
$stdout = new WritableResourceStream(STDOUT);
$stdout = new React\Stream\WritableResourceStream(STDOUT);

$stream = new Encoder($stdout);
$ndjson = new Clue\React\NDJson\Encoder($stdout);

$stream->write(array('name' => 'test', 'active' => true));
$stream->write(array('name' => 'hello wörld', 'active' => true));
$ndjson->write(array('name' => 'test', 'active' => true));
$ndjson->write(array('name' => 'hello wörld', 'active' => true));
```
```
{"name":"test","active":true}
Expand All @@ -248,13 +248,13 @@ $stream->write(array('name' => 'hello wörld', 'active' => true));

The `Encoder` supports the same parameters as the underlying
[`json_encode()`](https://www.php.net/manual/en/function.json-encode.php) function.
This means that, by default, unicode characters will be escaped in the output.
This means that, by default, Unicode characters will be escaped in the output.
This behavior can be controlled through the optional constructor parameters:

```php
$stream = new Encoder($stdout, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$ndjson = new Clue\React\NDJson\Encoder($stdout, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

$stream->write('hello wörld');
$ndjson->write('hello wörld');
```
```
"hello wörld"
Expand All @@ -268,7 +268,7 @@ any data that can not be represented as a valid NDJSON stream,
it will emit an `error` event and then `close` the input stream:

```php
$stream->on('error', function (Exception $error) {
$ndjson->on('error', function (Exception $error) {
// an error occured, stream will close next
});
```
Expand All @@ -277,7 +277,7 @@ If either the underlying stream or the `Encoder` is closed, it will forward
the `close` event:

```php
$stream->on('close', function () {
$ndjson->on('close', function () {
// stream closed
// possibly after an "end" event or due to an "error" event
});
Expand All @@ -287,22 +287,22 @@ The `end(mixed $data = null): void` method can be used to optionally emit
any final data and then soft-close the `Encoder` and its underlying stream:

```php
$stream->end();
$ndjson->end();
```

The `close(): void` method can be used to explicitly close the `Encoder` and
its underlying stream:

```php
$stream->close();
$ndjson->close();
```

For more details, see ReactPHP's
[`WritableStreamInterface`](https://github.com/reactphp/stream#writablestreaminterface).

## Install

The recommended way to install this library is [through Composer](https://getcomposer.org).
The recommended way to install this library is [through Composer](https://getcomposer.org/).
[New to Composer?](https://getcomposer.org/doc/00-intro.md)

This project follows [SemVer](https://semver.org/).
Expand All @@ -317,12 +317,12 @@ See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
This project aims to run on any platform and thus does not require any PHP
extensions and supports running on legacy PHP 5.3 through current PHP 8+ and
HHVM.
It's *highly recommended to use PHP 7+* for this project.
It's *highly recommended to use the latest supported PHP version* for this project.

## Tests

To run the test suite, you first need to clone this repo and then install all
dependencies [through Composer](https://getcomposer.org):
dependencies [through Composer](https://getcomposer.org/):

```bash
$ composer install
Expand All @@ -331,7 +331,7 @@ $ composer install
To run the test suite, go to the project root and run:

```bash
$ php vendor/bin/phpunit
$ vendor/bin/phpunit
```

## License
Expand Down
8 changes: 3 additions & 5 deletions examples/91-benchmark-count.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,18 @@
// 3) pipe NDJSON into benchmark script:
// $ php examples/91-benchmark-count.php < title.ratings.ndjson

use Clue\React\NDJson\Decoder;
use React\EventLoop\Loop;
use React\Stream\ReadableResourceStream;

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

if (extension_loaded('xdebug')) {
echo 'NOTICE: The "xdebug" extension is loaded, this has a major impact on performance.' . PHP_EOL;
}

$decoder = new Decoder(new ReadableResourceStream(STDIN), true);
$ndjson = new Clue\React\NDJson\Decoder(new React\Stream\ReadableResourceStream(STDIN), true);

$count = 0;
$decoder->on('data', function () use (&$count) {
$ndjson->on('data', function () use (&$count) {
++$count;
});

Expand All @@ -36,7 +34,7 @@
printf("\r%d records in %0.3fs...", $count, microtime(true) - $start);
});

$decoder->on('close', function () use (&$count, $report, $start) {
$ndjson->on('close', function () use (&$count, $report, $start) {
$now = microtime(true);
Loop::cancelTimer($report);

Expand Down
18 changes: 7 additions & 11 deletions examples/validate.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,20 @@

// $ php examples/validate.php < examples/users.ndjson

use Clue\React\NDJson\Decoder;
use Clue\React\NDJson\Encoder;
use React\EventLoop\Loop;
use React\Stream\ReadableResourceStream;
use React\Stream\WritableResourceStream;

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

$exit = 0;
$in = new ReadableResourceStream(STDIN);
$out = new WritableResourceStream(STDOUT);
$info = new WritableResourceStream(STDERR);
$in = new React\Stream\ReadableResourceStream(STDIN);
$out = new React\Stream\WritableResourceStream(STDOUT);
$info = new React\Stream\WritableResourceStream(STDERR);

$decoder = new Decoder($in);
$encoder = new Encoder($out);
$decoder->pipe($encoder);
$ndjson = new Clue\React\NDJson\Decoder($in);
$encoder = new Clue\React\NDJson\Encoder($out);
$ndjson->pipe($encoder);

$decoder->on('error', function (Exception $e) use ($info, &$exit) {
$ndjson->on('error', function (Exception $e) use ($info, &$exit) {
$info->write('ERROR: ' . $e->getMessage() . PHP_EOL);
$exit = 1;
});
Expand Down

0 comments on commit 5869138

Please sign in to comment.