diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:31:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:31:45 +0000 |
commit | 4e393913a4b1f06509da4341f0f58a41adac9117 (patch) | |
tree | 9c27e3eb77d109dff5fd031502311c5616adab04 /vendor/clue/block-react | |
parent | Initial commit. (diff) | |
download | icinga-php-thirdparty-upstream.tar.xz icinga-php-thirdparty-upstream.zip |
Adding upstream version 0.12.1+ds.upstream/0.12.1+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/clue/block-react')
-rw-r--r-- | vendor/clue/block-react/CHANGELOG.md | 152 | ||||
-rw-r--r-- | vendor/clue/block-react/LICENSE | 21 | ||||
-rw-r--r-- | vendor/clue/block-react/README.md | 335 | ||||
-rw-r--r-- | vendor/clue/block-react/composer.json | 29 | ||||
-rw-r--r-- | vendor/clue/block-react/src/functions.php | 357 | ||||
-rw-r--r-- | vendor/clue/block-react/src/functions_include.php | 8 |
6 files changed, 902 insertions, 0 deletions
diff --git a/vendor/clue/block-react/CHANGELOG.md b/vendor/clue/block-react/CHANGELOG.md new file mode 100644 index 0000000..5f145e9 --- /dev/null +++ b/vendor/clue/block-react/CHANGELOG.md @@ -0,0 +1,152 @@ +# Changelog + +## 1.5.0 (2021-10-20) + +* Feature: Simplify usage by supporting new [default loop](https://github.com/reactphp/event-loop#loop). + (#60 by @clue) + + ```php + // old (still supported) + Clue\React\Block\await($promise, $loop); + Clue\React\Block\awaitAny($promises, $loop); + Clue\React\Block\awaitAll($promises, $loop); + + // new (using default loop) + Clue\React\Block\await($promise); + Clue\React\Block\awaitAny($promises); + Clue\React\Block\awaitAll($promises); + ``` + +* Feature: Added support for upcoming react/promise v3. + (#61 by @davidcole1340 and @SimonFrings) + +* Improve error reporting by appending previous message for `Throwable`s. + (#57 by @clue) + +* Deprecate `$timeout` argument for `await*()` functions. + (#59 by @clue) + + ```php + // deprecated + Clue\React\Block\await($promise, $loop, $timeout); + Clue\React\Block\awaitAny($promises, $loop, $timeout); + Clue\React\Block\awaitAll($promises, $loop, $timeout); + + // still supported + Clue\React\Block\await($promise, $loop); + Clue\React\Block\awaitAny($promises, $loop); + Clue\React\Block\awaitAll($promises, $loop); + ``` + +* Improve API documentation. + (#58 and #63 by @clue and #55 by @PaulRotmann) + +* Improve test suite and use GitHub actions for continuous integration (CI). + (#54 by @SimonFrings) + +## 1.4.0 (2020-08-21) + +* Improve API documentation, update README and add examples. + (#45 by @clue and #51 by @SimonFrings) + +* Improve test suite and add `.gitattributes` to exclude dev files from exports. + Prepare PHP 8 support, update to PHPUnit 9, run tests on PHP 7.4 and simplify test matrix. + (#46, #47 and #50 by @SimonFrings) + +## 1.3.1 (2019-04-09) + +* Fix: Fix getting the type of unexpected rejection reason when not rejecting with an `Exception`. + (#42 by @Furgas and @clue) + +* Fix: Check if the function is declared before declaring it. + (#39 by @Niko9911) + +## 1.3.0 (2018-06-14) + +* Feature: Improve memory consumption by cleaning up garbage references. + (#35 by @clue) + +* Fix minor documentation typos. + (#28 by @seregazhuk) + +* Improve test suite by locking Travis distro so new defaults will not break the build, + support PHPUnit 6 and update Travis config to also test against PHP 7.2. + (#30 by @clue, #31 by @carusogabriel and #32 by @andreybolonin) + +* Update project homepage. + (#34 by @clue) + +## 1.2.0 (2017-08-03) + +* Feature / Fix: Forward compatibility with future EventLoop v1.0 and v0.5 and + cap small timeout values for legacy EventLoop + (#26 by @clue) + + ```php + // now works across all versions + Block\sleep(0.000001, $loop); + ``` + +* Feature / Fix: Throw `UnexpectedValueException` if Promise gets rejected with non-Exception + (#27 by @clue) + + ```php + // now throws an UnexceptedValueException + Block\await(Promise\reject(false), $loop); + ``` + +* First class support for legacy PHP 5.3 through PHP 7.1 and HHVM + (#24 and #25 by @clue) + +* Improve testsuite by adding PHPUnit to require-dev and + Fix HHVM build for now again and ignore future HHVM build errors + (#23 and #24 by @clue) + +## 1.1.0 (2016-03-09) + +* Feature: Add optional timeout parameter to all await*() functions + (#17 by @clue) + +* Feature: Cancellation is now supported across all PHP versions + (#16 by @clue) + +## 1.0.0 (2015-11-13) + +* First stable release, now following SemVer +* Improved documentation + +> Contains no other changes, so it's actually fully compatible with the v0.3.0 release. + +## 0.3.0 (2015-07-09) + +* BC break: Use functional API approach instead of pseudo-OOP. + All existing methods are now exposed as simple functions. + ([#13](https://github.com/clue/php-block-react/pull/13)) + ```php +// old +$blocker = new Block\Blocker($loop); +$result = $blocker->await($promise); + +// new +$result = Block\await($promise, $loop); +``` + +## 0.2.0 (2015-07-05) + +* BC break: Rename methods in order to avoid confusion. + * Rename `wait()` to `sleep()`. + ([#8](https://github.com/clue/php-block-react/pull/8)) + * Rename `awaitRace()` to `awaitAny()`. + ([#9](https://github.com/clue/php-block-react/pull/9)) + * Rename `awaitOne()` to `await()`. + ([#10](https://github.com/clue/php-block-react/pull/10)) + +## 0.1.1 (2015-04-05) + +* `run()` the loop instead of making it `tick()`. + This results in significant performance improvements (less resource utilization) by avoiding busy waiting + ([#1](https://github.com/clue/php-block-react/pull/1)) + +## 0.1.0 (2015-04-04) + +* First tagged release diff --git a/vendor/clue/block-react/LICENSE b/vendor/clue/block-react/LICENSE new file mode 100644 index 0000000..dc09d1e --- /dev/null +++ b/vendor/clue/block-react/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Christian Lück + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/clue/block-react/README.md b/vendor/clue/block-react/README.md new file mode 100644 index 0000000..d000a16 --- /dev/null +++ b/vendor/clue/block-react/README.md @@ -0,0 +1,335 @@ +# clue/reactphp-block + +[](https://github.com/clue/reactphp-block/actions) +[](https://packagist.org/packages/clue/block-react) + +Lightweight library that eases integrating async components built for +[ReactPHP](https://reactphp.org/) in a traditional, blocking environment. + +[ReactPHP](https://reactphp.org/) provides you a great set of base components and +a huge ecosystem of third party libraries in order to perform async operations. +The event-driven paradigm and asynchronous processing of any number of streams +in real time enables you to build a whole new set of application on top of it. +This is great for building modern, scalable applications from scratch and will +likely result in you relying on a whole new software architecture. + +But let's face it: Your day-to-day business is unlikely to allow you to build +everything from scratch and ditch your existing production environment. +This is where this library comes into play: + +*Let's block ReactPHP* +More specifically, this library eases the pain of integrating async components +into your traditional, synchronous (blocking) application stack. + +**Table of contents** + +* [Support us](#support-us) +* [Quickstart example](#quickstart-example) +* [Usage](#usage) + * [sleep()](#sleep) + * [await()](#await) + * [awaitAny()](#awaitany) + * [awaitAll()](#awaitall) +* [Install](#install) +* [Tests](#tests) +* [License](#license) + +## Support us + +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) +for details. + +Let's take these projects to the next level together! 🚀 + +### Quickstart example + +The following example code demonstrates how this library can be used along with +an [async HTTP client](https://github.com/reactphp/http#client-usage) to process two +non-blocking HTTP requests and block until the first (faster) one resolves. + +```php +function blockingExample() +{ + // this example uses an HTTP client + // this could be pretty much everything that binds to an event loop + $browser = new React\Http\Browser(); + + // set up two parallel requests + $request1 = $browser->get('http://www.google.com/'); + $request2 = $browser->get('http://www.google.co.uk/'); + + // keep the loop running (i.e. block) until the first response arrives + $fasterResponse = Clue\React\Block\awaitAny(array($request1, $request2)); + + return $fasterResponse->getBody(); +} +``` + +## Usage + +This lightweight library consists only of a few simple functions. +All functions reside under the `Clue\React\Block` namespace. + +The below examples refer to all functions with their fully-qualified names like this: + +```php +Clue\React\Block\await(…); +``` + +As of PHP 5.6+ you can also import each required function into your code like this: + +```php +use function Clue\React\Block\await; + +await(…); +``` + +Alternatively, you can also use an import statement similar to this: + +```php +use Clue\React\Block; + +Block\await(…); +``` + +### sleep() + +The `sleep(float $seconds, ?LoopInterface $loop = null): void` function can be used to +wait/sleep for `$time` seconds. + +```php +Clue\React\Block\sleep(1.5, $loop); +``` + +This function will only return after the given `$time` has elapsed. In the +meantime, the event loop will run any other events attached to the same loop +until the timer fires. If there are no other events attached to this loop, +it will behave similar to the built-in [`sleep()`](https://www.php.net/manual/en/function.sleep.php). + +Internally, the `$time` argument will be used as a timer for the loop so that +it keeps running until this timer triggers. This implies that if you pass a +really small (or negative) value, it will still start a timer and will thus +trigger at the earliest possible time in the future. + +This function takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use. 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. + +Note that this function will assume control over the event loop. Internally, it +will actually `run()` the loop until the timer fires and then calls `stop()` to +terminate execution of the loop. This means this function is more suited for +short-lived program executions when using async APIs is not feasible. For +long-running applications, using event-driven APIs by leveraging timers +is usually preferable. + +### await() + +The `await(PromiseInterface $promise, ?LoopInterface $loop = null, ?float $timeout = null): mixed` function can be used to +block waiting for the given `$promise` to be fulfilled. + +```php +$result = Clue\React\Block\await($promise); +``` + +This function will only return after the given `$promise` has settled, i.e. +either fulfilled or rejected. In the meantime, the event loop will run any +events attached to the same loop until the promise settles. + +Once the promise is fulfilled, this function will return whatever the promise +resolved to. + +Once the promise is rejected, this will throw whatever the promise rejected +with. If the promise did not reject with an `Exception`, then this function +will throw an `UnexpectedValueException` instead. + +```php +try { + $result = Clue\React\Block\await($promise); + // promise successfully fulfilled with $result + echo 'Result: ' . $result; +} catch (Exception $exception) { + // promise rejected with $exception + echo 'ERROR: ' . $exception->getMessage(); +} +``` + +See also the [examples](examples/). + +This function takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use. 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 no `$timeout` argument is given and the promise stays pending, then this +will potentially wait/block forever until the promise is settled. To avoid +this, API authors creating promises are expected to provide means to +configure a timeout for the promise instead. For more details, see also the +[`timeout()` function](https://github.com/reactphp/promise-timer#timeout). + +If the deprecated `$timeout` argument is given and the promise is still pending once the +timeout triggers, this will `cancel()` the promise and throw a `TimeoutException`. +This implies that if you pass a really small (or negative) value, it will still +start a timer and will thus trigger at the earliest possible time in the future. + +Note that this function will assume control over the event loop. Internally, it +will actually `run()` the loop until the promise settles and then calls `stop()` to +terminate execution of the loop. This means this function is more suited for +short-lived promise executions when using promise-based APIs is not feasible. +For long-running applications, using promise-based APIs by leveraging chained +`then()` calls is usually preferable. + +### awaitAny() + +The `awaitAny(PromiseInterface[] $promises, ?LoopInterface $loop = null, ?float $timeout = null): mixed` function can be used to +wait for ANY of the given promises to be fulfilled. + +```php +$promises = array( + $promise1, + $promise2 +); + +$firstResult = Clue\React\Block\awaitAny($promises); + +echo 'First result: ' . $firstResult; +``` + +See also the [examples](examples/). + +This function will only return after ANY of the given `$promises` has been +fulfilled or will throw when ALL of them have been rejected. In the meantime, +the event loop will run any events attached to the same loop. + +Once ANY promise is fulfilled, this function will return whatever this +promise resolved to and will try to `cancel()` all remaining promises. + +Once ALL promises reject, this function will fail and throw an `UnderflowException`. +Likewise, this will throw if an empty array of `$promises` is passed. + +This function takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use. 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 no `$timeout` argument is given and ALL promises stay pending, then this +will potentially wait/block forever until the promise is fulfilled. To avoid +this, API authors creating promises are expected to provide means to +configure a timeout for the promise instead. For more details, see also the +[`timeout()` function](https://github.com/reactphp/promise-timer#timeout). + +If the deprecated `$timeout` argument is given and ANY promises are still pending once +the timeout triggers, this will `cancel()` all pending promises and throw a +`TimeoutException`. This implies that if you pass a really small (or negative) +value, it will still start a timer and will thus trigger at the earliest +possible time in the future. + +Note that this function will assume control over the event loop. Internally, it +will actually `run()` the loop until the promise settles and then calls `stop()` to +terminate execution of the loop. This means this function is more suited for +short-lived promise executions when using promise-based APIs is not feasible. +For long-running applications, using promise-based APIs by leveraging chained +`then()` calls is usually preferable. + +### awaitAll() + +The `awaitAll(PromiseInterface[] $promises, ?LoopInterface $loop = null, ?float $timeout = null): mixed[]` function can be used to +wait for ALL of the given promises to be fulfilled. + +```php +$promises = array( + $promise1, + $promise2 +); + +$allResults = Clue\React\Block\awaitAll($promises); + +echo 'First promise resolved with: ' . $allResults[0]; +``` + +See also the [examples](examples/). + +This function will only return after ALL of the given `$promises` have been +fulfilled or will throw when ANY of them have been rejected. In the meantime, +the event loop will run any events attached to the same loop. + +Once ALL promises are fulfilled, this will return an array with whatever +each promise resolves to. Array keys will be left intact, i.e. they can +be used to correlate the return array to the promises passed. +Likewise, this will return an empty array if an empty array of `$promises` is passed. + +Once ANY promise rejects, this will try to `cancel()` all remaining promises +and throw an `Exception`. If the promise did not reject with an `Exception`, +then this function will throw an `UnexpectedValueException` instead. + +This function takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use. 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 no `$timeout` argument is given and ANY promises stay pending, then this +will potentially wait/block forever until the promise is fulfilled. To avoid +this, API authors creating promises are expected to provide means to +configure a timeout for the promise instead. For more details, see also the +[`timeout()` function](https://github.com/reactphp/promise-timer#timeout). + +If the deprecated `$timeout` argument is given and ANY promises are still pending once +the timeout triggers, this will `cancel()` all pending promises and throw a +`TimeoutException`. This implies that if you pass a really small (or negative) +value, it will still start a timer and will thus trigger at the earliest +possible time in the future. + +Note that this function will assume control over the event loop. Internally, it +will actually `run()` the loop until the promise settles and then calls `stop()` to +terminate execution of the loop. This means this function is more suited for +short-lived promise executions when using promise-based APIs is not feasible. +For long-running applications, using promise-based APIs by leveraging chained +`then()` calls is usually preferable. + +## Install + +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/). +This will install the latest supported version: + +```bash +$ composer require clue/block-react:^1.5 +``` + +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 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/): + +```bash +$ composer install +``` + +To run the test suite, go to the project root and run: + +```bash +$ vendor/bin/phpunit +``` + +## 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. diff --git a/vendor/clue/block-react/composer.json b/vendor/clue/block-react/composer.json new file mode 100644 index 0000000..ddfc6c8 --- /dev/null +++ b/vendor/clue/block-react/composer.json @@ -0,0 +1,29 @@ +{ + "name": "clue/block-react", + "description": "Lightweight library that eases integrating async components built for ReactPHP in a traditional, blocking environment.", + "keywords": ["blocking", "await", "sleep", "Event Loop", "synchronous", "Promise", "ReactPHP", "async"], + "homepage": "https://github.com/clue/reactphp-block", + "license": "MIT", + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "autoload": { + "files": [ "src/functions_include.php" ] + }, + "autoload-dev": { + "psr-4": { "Clue\\Tests\\React\\Block\\": "tests/" } + }, + "require": { + "php": ">=5.3", + "react/event-loop": "^1.2", + "react/promise": "^3.0 || ^2.7 || ^1.2.1", + "react/promise-timer": "^1.5" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/http": "^1.4" + } +} diff --git a/vendor/clue/block-react/src/functions.php b/vendor/clue/block-react/src/functions.php new file mode 100644 index 0000000..6afe2e0 --- /dev/null +++ b/vendor/clue/block-react/src/functions.php @@ -0,0 +1,357 @@ +<?php + +namespace Clue\React\Block; + +use React\EventLoop\Loop; +use React\EventLoop\LoopInterface; +use React\Promise; +use React\Promise\CancellablePromiseInterface; +use React\Promise\PromiseInterface; +use React\Promise\Timer; +use React\Promise\Timer\TimeoutException; +use Exception; +use UnderflowException; + +/** + * Wait/sleep for `$time` seconds. + * + * ```php + * Clue\React\Block\sleep(1.5, $loop); + * ``` + * + * This function will only return after the given `$time` has elapsed. In the + * meantime, the event loop will run any other events attached to the same loop + * until the timer fires. If there are no other events attached to this loop, + * it will behave similar to the built-in [`sleep()`](https://www.php.net/manual/en/function.sleep.php). + * + * Internally, the `$time` argument will be used as a timer for the loop so that + * it keeps running until this timer triggers. This implies that if you pass a + * really small (or negative) value, it will still start a timer and will thus + * trigger at the earliest possible time in the future. + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. 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. + * + * Note that this function will assume control over the event loop. Internally, it + * will actually `run()` the loop until the timer fires and then calls `stop()` to + * terminate execution of the loop. This means this function is more suited for + * short-lived program executions when using async APIs is not feasible. For + * long-running applications, using event-driven APIs by leveraging timers + * is usually preferable. + * + * @param float $time + * @param ?LoopInterface $loop + * @return void + */ +function sleep($time, LoopInterface $loop = null) +{ + await(Timer\resolve($time, $loop), $loop); +} + +/** + * Block waiting for the given `$promise` to be fulfilled. + * + * ```php + * $result = Clue\React\Block\await($promise, $loop); + * ``` + * + * This function will only return after the given `$promise` has settled, i.e. + * either fulfilled or rejected. In the meantime, the event loop will run any + * events attached to the same loop until the promise settles. + * + * Once the promise is fulfilled, this function will return whatever the promise + * resolved to. + * + * Once the promise is rejected, this will throw whatever the promise rejected + * with. If the promise did not reject with an `Exception`, then this function + * will throw an `UnexpectedValueException` instead. + * + * ```php + * try { + * $result = Clue\React\Block\await($promise, $loop); + * // promise successfully fulfilled with $result + * echo 'Result: ' . $result; + * } catch (Exception $exception) { + * // promise rejected with $exception + * echo 'ERROR: ' . $exception->getMessage(); + * } + * ``` + * + * See also the [examples](../examples/). + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. 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 no `$timeout` argument is given and the promise stays pending, then this + * will potentially wait/block forever until the promise is settled. To avoid + * this, API authors creating promises are expected to provide means to + * configure a timeout for the promise instead. For more details, see also the + * [`timeout()` function](https://github.com/reactphp/promise-timer#timeout). + * + * If the deprecated `$timeout` argument is given and the promise is still pending once the + * timeout triggers, this will `cancel()` the promise and throw a `TimeoutException`. + * This implies that if you pass a really small (or negative) value, it will still + * start a timer and will thus trigger at the earliest possible time in the future. + * + * Note that this function will assume control over the event loop. Internally, it + * will actually `run()` the loop until the promise settles and then calls `stop()` to + * terminate execution of the loop. This means this function is more suited for + * short-lived promise executions when using promise-based APIs is not feasible. + * For long-running applications, using promise-based APIs by leveraging chained + * `then()` calls is usually preferable. + * + * @param PromiseInterface $promise + * @param ?LoopInterface $loop + * @param ?float $timeout [deprecated] (optional) maximum timeout in seconds or null=wait forever + * @return mixed returns whatever the promise resolves to + * @throws Exception when the promise is rejected + * @throws TimeoutException if the $timeout is given and triggers + */ +function await(PromiseInterface $promise, LoopInterface $loop = null, $timeout = null) +{ + $wait = true; + $resolved = null; + $exception = null; + $rejected = false; + $loop = $loop ?: Loop::get(); + + if ($timeout !== null) { + $promise = Timer\timeout($promise, $timeout, $loop); + } + + $promise->then( + function ($c) use (&$resolved, &$wait, $loop) { + $resolved = $c; + $wait = false; + $loop->stop(); + }, + function ($error) use (&$exception, &$rejected, &$wait, $loop) { + $exception = $error; + $rejected = true; + $wait = false; + $loop->stop(); + } + ); + + // Explicitly overwrite argument with null value. This ensure that this + // argument does not show up in the stack trace in PHP 7+ only. + $promise = null; + + while ($wait) { + $loop->run(); + } + + if ($rejected) { + if (!$exception instanceof \Exception && !$exception instanceof \Throwable) { + $exception = new \UnexpectedValueException( + 'Promise rejected with unexpected value of type ' . (is_object($exception) ? get_class($exception) : gettype($exception)) + ); + } elseif (!$exception instanceof \Exception) { + $exception = new \UnexpectedValueException( + 'Promise rejected with unexpected ' . get_class($exception) . ': ' . $exception->getMessage(), + $exception->getCode(), + $exception + ); + } + + throw $exception; + } + + return $resolved; +} + +/** + * Wait for ANY of the given promises to be fulfilled. + * + * ```php + * $promises = array( + * $promise1, + * $promise2 + * ); + * + * $firstResult = Clue\React\Block\awaitAny($promises, $loop); + * + * echo 'First result: ' . $firstResult; + * ``` + * + * See also the [examples](../examples/). + * + * This function will only return after ANY of the given `$promises` has been + * fulfilled or will throw when ALL of them have been rejected. In the meantime, + * the event loop will run any events attached to the same loop. + * + * Once ANY promise is fulfilled, this function will return whatever this + * promise resolved to and will try to `cancel()` all remaining promises. + * + * Once ALL promises reject, this function will fail and throw an `UnderflowException`. + * Likewise, this will throw if an empty array of `$promises` is passed. + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. 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 no `$timeout` argument is given and ALL promises stay pending, then this + * will potentially wait/block forever until the promise is fulfilled. To avoid + * this, API authors creating promises are expected to provide means to + * configure a timeout for the promise instead. For more details, see also the + * [`timeout()` function](https://github.com/reactphp/promise-timer#timeout). + * + * If the deprecated `$timeout` argument is given and ANY promises are still pending once + * the timeout triggers, this will `cancel()` all pending promises and throw a + * `TimeoutException`. This implies that if you pass a really small (or negative) + * value, it will still start a timer and will thus trigger at the earliest + * possible time in the future. + * + * Note that this function will assume control over the event loop. Internally, it + * will actually `run()` the loop until the promise settles and then calls `stop()` to + * terminate execution of the loop. This means this function is more suited for + * short-lived promise executions when using promise-based APIs is not feasible. + * For long-running applications, using promise-based APIs by leveraging chained + * `then()` calls is usually preferable. + * + * @param PromiseInterface[] $promises + * @param ?LoopInterface $loop + * @param ?float $timeout [deprecated] (optional) maximum timeout in seconds or null=wait forever + * @return mixed returns whatever the first promise resolves to + * @throws Exception if ALL promises are rejected + * @throws TimeoutException if the $timeout is given and triggers + */ +function awaitAny(array $promises, LoopInterface $loop = null, $timeout = null) +{ + // Explicitly overwrite argument with null value. This ensure that this + // argument does not show up in the stack trace in PHP 7+ only. + $all = $promises; + $promises = null; + + try { + // Promise\any() does not cope with an empty input array, so reject this here + if (!$all) { + throw new UnderflowException('Empty input array'); + } + + $ret = await(Promise\any($all)->then(null, function () { + // rejects with an array of rejection reasons => reject with Exception instead + throw new Exception('All promises rejected'); + }), $loop, $timeout); + } catch (TimeoutException $e) { + // the timeout fired + // => try to cancel all promises (rejected ones will be ignored anyway) + _cancelAllPromises($all); + + throw $e; + } catch (Exception $e) { + // if the above throws, then ALL promises are already rejected + // => try to cancel all promises (rejected ones will be ignored anyway) + _cancelAllPromises($all); + + throw new UnderflowException('No promise could resolve', 0, $e); + } + + // if we reach this, then ANY of the given promises resolved + // => try to cancel all promises (settled ones will be ignored anyway) + _cancelAllPromises($all); + + return $ret; +} + +/** + * Wait for ALL of the given promises to be fulfilled. + * + * ```php + * $promises = array( + * $promise1, + * $promise2 + * ); + * + * $allResults = Clue\React\Block\awaitAll($promises, $loop); + * + * echo 'First promise resolved with: ' . $allResults[0]; + * ``` + * + * See also the [examples](../examples/). + * + * This function will only return after ALL of the given `$promises` have been + * fulfilled or will throw when ANY of them have been rejected. In the meantime, + * the event loop will run any events attached to the same loop. + * + * Once ALL promises are fulfilled, this will return an array with whatever + * each promise resolves to. Array keys will be left intact, i.e. they can + * be used to correlate the return array to the promises passed. + * + * Once ANY promise rejects, this will try to `cancel()` all remaining promises + * and throw an `Exception`. If the promise did not reject with an `Exception`, + * then this function will throw an `UnexpectedValueException` instead. + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. 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 no `$timeout` argument is given and ANY promises stay pending, then this + * will potentially wait/block forever until the promise is fulfilled. To avoid + * this, API authors creating promises are expected to provide means to + * configure a timeout for the promise instead. For more details, see also the + * [`timeout()` function](https://github.com/reactphp/promise-timer#timeout). + * + * If the deprecated `$timeout` argument is given and ANY promises are still pending once + * the timeout triggers, this will `cancel()` all pending promises and throw a + * `TimeoutException`. This implies that if you pass a really small (or negative) + * value, it will still start a timer and will thus trigger at the earliest + * possible time in the future. + * + * Note that this function will assume control over the event loop. Internally, it + * will actually `run()` the loop until the promise settles and then calls `stop()` to + * terminate execution of the loop. This means this function is more suited for + * short-lived promise executions when using promise-based APIs is not feasible. + * For long-running applications, using promise-based APIs by leveraging chained + * `then()` calls is usually preferable. + * + * @param PromiseInterface[] $promises + * @param ?LoopInterface $loop + * @param ?float $timeout [deprecated] (optional) maximum timeout in seconds or null=wait forever + * @return array returns an array with whatever each promise resolves to + * @throws Exception when ANY promise is rejected + * @throws TimeoutException if the $timeout is given and triggers + */ +function awaitAll(array $promises, LoopInterface $loop = null, $timeout = null) +{ + // Explicitly overwrite argument with null value. This ensure that this + // argument does not show up in the stack trace in PHP 7+ only. + $all = $promises; + $promises = null; + + try { + return await(Promise\all($all), $loop, $timeout); + } catch (Exception $e) { + // ANY of the given promises rejected or the timeout fired + // => try to cancel all promises (rejected ones will be ignored anyway) + _cancelAllPromises($all); + + throw $e; + } +} + +/** + * internal helper function used to iterate over an array of Promise instances and cancel() each + * + * @internal + * @param array $promises + * @return void + */ +function _cancelAllPromises(array $promises) +{ + foreach ($promises as $promise) { + if ($promise instanceof PromiseInterface && ($promise instanceof CancellablePromiseInterface || !\interface_exists('React\Promise\CancellablePromiseInterface'))) { + $promise->cancel(); + } + } +} diff --git a/vendor/clue/block-react/src/functions_include.php b/vendor/clue/block-react/src/functions_include.php new file mode 100644 index 0000000..b3ad74c --- /dev/null +++ b/vendor/clue/block-react/src/functions_include.php @@ -0,0 +1,8 @@ +<?php + +namespace Clue\React\Block; + +if (!function_exists('Clue\\React\\Block\\sleep')) { + require __DIR__ . '/functions.php'; +} + |