Skip to content

Update documentation and examples to match version in early access #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/composer.lock
/vendor/
116 changes: 107 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,32 @@
PQ ("peak"), automatically wrap blocking functions in an async child process and turn blocking functions into non-blocking promises,
built on top of [ReactPHP](https://reactphp.org/).

**Table of contents**

* [Support us](#support-us)
* [Quickstart example](#quickstart-example)
* [Install](#install)
* [Usage](#usage)
* [Executor](#executor)
* [fun()](#fun)
* [Tests](#tests)
* [License](#license)

## Support us

[![A clue·access project](https://raw.githubusercontent.com/clue-access/clue-access/main/clue-access.png)](https://github.com/clue-access/clue-access)

*This project is currently under active development,
you're looking at a temporary placeholder repository.*

The code is available in early access to my sponsors here: https://github.com/clue-access/reactphp-pq

Do you sponsor me on GitHub? Thank you for supporting sustainable open-source, you're awesome! ❤️ Have fun with the code! 🎉

Seeing a 404 (Not Found)? Sounds like you're not in the early access group. Consider becoming a [sponsor on GitHub](https://github.com/sponsors/clue) for early access. Check out [clue·access](https://github.com/clue-access/clue-access) for more details.

This way, more people get a chance to take a look at the code before the public release.

## Quickstart example

Once [installed](#install), you can use the following code turn any blocking function (such as PHP's built-in [`file_get_contents()`](https://www.php.net/manual/en/function.file-get-contents.php) function) into a non-blocking one:
Expand All @@ -22,26 +48,98 @@ $file_get_contents(__FILE__)->then(function (string $contents) {
});
```

## Usage

### Executor

The `Executor` is responsible for managing process executions.

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.

```php
$executor = Clue\React\Pq\Executor();
```

#### fun()

The `fun(string $function): callable` method can be used to
return an async callable for the given global blocking function name.

This method returns an async callable that will return a promise when
invoked. The promise will eventually fulfill with the return value of the
function on success or reject with an `Exception` on error:

```php
$executor = new Clue\React\Pq\Executor();
$file_get_contents = $executor->fun('file_get_contents');

$file_get_contents(__FILE__)->then(function (string $contents) {
echo $contents;
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});
```

You can pass any number of arguments that will be passed to the given
function. The function will be executed in a child process and as such
will not block the execution of the parent process.

The callable can be invoked any number of times, each function call will
take place in a separate child process. Once completed, child processes
may be reused internally.

## Install

[![A clue·access project](https://raw.githubusercontent.com/clue-access/clue-access/main/clue-access.png)](https://github.com/clue-access/clue-access)
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 is currently under active development,
you're looking at a temporary placeholder repository.*
This project does not yet follow [SemVer](https://semver.org/).
This will install the latest supported version:

The code is available in early access to my sponsors here: https://github.com/clue-access/reactphp-pq
While in beta, you first have to manually change your `composer.json` to include these lines:

Do you sponsor me on GitHub? Thank you for supporting sustainable open-source, you're awesome! ❤️ Have fun with the code! 🎉
```json
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/clue-access/reactphp-pq"
}
]
}
```

Seeing a 404 (Not Found)? Sounds like you're not in the early access group. Consider becoming a [sponsor on GitHub](https://github.com/sponsors/clue) for early access. Check out [clue·access](https://github.com/clue-access/clue-access) for more details.
Then install this package as usual:

This way, more people get a chance to take a look at the code before the public release.
```bash
$ composer require clue/reactphp-pq:dev-main
```

This project aims to run on any platform and thus does not require any PHP
extensions and supports running on PHP 7 through current PHP 8+.

Rock on 🤘
## Tests

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

```bash
$ composer install
```

To run the test suite, go to the project root and run:

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

## License

This project will be released under the permissive [MIT license](LICENSE).
This project is released under the permissive [MIT license](LICENSE).

> Did you know that I offer custom development services and issuing invoices for
sponsorships of releases and for contributions? Contact me (@clue) for details.
13 changes: 13 additions & 0 deletions examples/01-file-get-contents.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

// $ php examples/01-file-get-contents.php

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

$file_get_contents = (new Clue\React\Pq\Executor())->fun('file_get_contents');

$file_get_contents(__FILE__)->then(function ($contents) {
echo $contents;
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});
20 changes: 20 additions & 0 deletions examples/02-multiple-sleep.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

// $ php examples/02-multiple-sleep.php

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

$sleep = (new Clue\React\Pq\Executor())->fun('sleep');

$promises = [
$sleep(2),
$sleep(3),
$sleep(2)
];

$promise = React\Promise\all($promises);
$promise->then(function ($results) {
var_dump($results);
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});
21 changes: 21 additions & 0 deletions examples/11-multiple-file-get-contents.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

// $ php examples/11-multiple-file-get-contents.php

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

$n = isset($argv[1]) ? (int)$argv[1] : 100;

$file_get_contents = (new Clue\React\Pq\Executor())->fun('file_get_contents');
$q = new Clue\React\Mq\Queue(16, null, $file_get_contents);

$promises = [];
for ($i = 0; $i < $n; ++$i) {
$promises[] = $q(__FILE__);
}

React\Promise\all($promises)->then(function ($results) {
echo 'Loaded ' . count($results) . PHP_EOL;
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});