Skip to content

Commit c99a670

Browse files
authoredApr 25, 2023
Merge pull request #4 from ace411/v0.x
v0.2.2 fixes
2 parents 6b2f3b2 + f6ce90f commit c99a670

File tree

9 files changed

+110
-19
lines changed

9 files changed

+110
-19
lines changed
 

‎README.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,19 @@ $exec = Async::create()
7070

7171
The examples directory contains more nuanced uses of the library that I recommend you check out.
7272

73-
## Limitation
73+
## Limitations
7474

75-
`asyncify` is no panacea, but is capable of asynchronously executing a plethora of blocking calls. As presently constituted, the library is incapable of processing inputs and outputs that cannot be serialized.
75+
- `asyncify` is no panacea, but is capable of asynchronously executing a plethora of blocking calls. As presently constituted, the library is **incapable of processing inputs and outputs that cannot be serialized**. Its quintessential asynchronous function application primitive - `call()` - works almost exclusively with string encodings of native language functions and lambdas imported via an autoloading mechanism.
76+
77+
- The library cannot parse closures. All executable arbitrary code should be emplaced in a string whose sole constituent is an immediately invokable anonymous function the format of which is `(function (...$args) { /* signature */ })`.
7678

7779
## API Reference
7880

7981
### Object
8082

8183
```php
84+
namespace Chemem\Asyncify;
85+
8286
class Async {
8387

8488
/* Methods */
@@ -94,6 +98,8 @@ class Async {
9498
### Function
9599

96100
```php
101+
namespace Chemem\Asyncify;
102+
97103
call ( string $func [, array $args [, ?string $autoload = null [, ?React\EventLoop\LoopInterface $args = null ] ] ] ) : React\Promise\PromiseInterface;
98104
```
99105

‎composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"php": ">=7.2",
1515
"chemem/bingo-functional": "~2",
1616
"react/child-process": "~0",
17-
"react/promise-stream": "~1"
17+
"react/promise": "~2"
1818
},
1919
"require-dev": {
2020
"ergebnis/composer-normalize": "~2",

‎src/Async.php

+14
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,20 @@ public static function create(?string $autoload = null, ?LoopInterface $loop = n
6363
* @param string $function
6464
* @param array $args
6565
* @return PromiseInterface
66+
* @example
67+
*
68+
* $async = Async::create('/path/to/autoload.php');
69+
* $res = $async
70+
* ->call('file_get_contents', ['path/to/file'])
71+
* ->then(
72+
* function (string $contents) {
73+
* echo $contents . PHP_EOL;
74+
* },
75+
* function (Throwable $err) {
76+
* echo $err->getMessage() . PHP_EOL;
77+
* }
78+
* )
79+
* => file_get_contents(/path/to/file): Failed to open stream: No such file or directory
6680
*/
6781
public function call(string $function, array $args): PromiseInterface
6882
{

‎src/call.php

+12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@
2525
*
2626
* @param mixed ...$args
2727
* @return mixed
28+
* @example
29+
*
30+
* call('file_get_contents', ['path/to/file'])
31+
* ->then(
32+
* function (string $contents) {
33+
* echo $contents . PHP_EOL;
34+
* },
35+
* function (Throwable $err) {
36+
* echo $err->getMessage() . PHP_EOL;
37+
* }
38+
* )
39+
* => file_get_contents(/path/to/file): Failed to open stream: No such file or directory
2840
*/
2941
function call(...$args)
3042
{

‎src/internal/asyncify.php

+12
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@
3535
* @param string|null $autoload
3636
* @param LoopInterface|null $loop
3737
* @return PromiseInterface
38+
* @example
39+
*
40+
* $data = asyncify('file_get_contents', ['path/to/file'])
41+
* ->then(
42+
* function (string $contents) {
43+
* echo $contents . PHP_EOL;
44+
* },
45+
* function (Throwable $err) {
46+
* echo $err->getMessage() . PHP_EOL;
47+
* }
48+
* )
49+
* => file_get_contents(/path/to/file): Failed to open stream: No such file or directory
3850
*/
3951
function asyncify(
4052
string $function,

‎src/internal/constants.php

+6-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
const PHP_EXECUTABLE_TEMPLATE = <<<'PHP'
1919
function handleException(Throwable $exception): void
2020
{
21-
echo "Exception: " . $exception->getMessage();
21+
echo $exception->getMessage();
2222
}
2323
function handleError(...$args)
2424
{
@@ -34,7 +34,11 @@ function (...$args) {
3434
return %s(...$args);
3535
},
3636
function ($err) {
37-
return new \Exception("Exception: " . $err->getMessage());
37+
return new \Exception(
38+
$err->getMessage(),
39+
$err->getCode(),
40+
$err->getPrevious()
41+
);
3842
}
3943
)(...\unserialize(\base64_decode("%s")))
4044
)

‎src/internal/proc.php

+52-9
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,9 @@
1414

1515
use React\ChildProcess\Process;
1616
use React\EventLoop\LoopInterface;
17+
use React\Promise\Deferred;
1718
use React\Promise\PromiseInterface;
1819

19-
use function React\Promise\reject;
20-
use function React\Promise\Stream\buffer;
21-
2220
const proc = __NAMESPACE__ . '\\proc';
2321

2422
/**
@@ -33,19 +31,64 @@
3331
* @return PromiseInterface
3432
* @example
3533
*
36-
* proc('php -r "echo 12;"')
37-
* => object(React\Promise\Promise) {}
34+
* proc('php -r "echo 12 . PHP_EOL;"')
35+
* ->then(
36+
* function ($result) {
37+
* echo $result;
38+
* }
39+
* )
40+
* => 12
3841
*/
3942
function proc(string $process, ?LoopInterface $loop = null): PromiseInterface
4043
{
41-
$proc = new Process($process);
44+
$proc = new Process($process);
45+
$result = new Deferred();
4246
$proc->start($loop);
4347

4448
if (!$proc->stdout->isReadable()) {
45-
return reject(
46-
new \Exception(\sprintf('Could not process %s', $process))
49+
$result->reject(
50+
new \Exception(
51+
\sprintf('Could not process "%s"', $process)
52+
)
4753
);
54+
55+
return $result;
4856
}
4957

50-
return buffer($proc->stdout);
58+
$proc->stdout->on(
59+
'data',
60+
function ($chunk) use (&$result) {
61+
$result->resolve($chunk);
62+
}
63+
);
64+
65+
// reject promise in the event of failure
66+
$proc->stdout->on(
67+
'error',
68+
function (\Throwable $err) use (&$result, &$proc) {
69+
$result->reject($err);
70+
}
71+
);
72+
73+
// handle successful closure of the process stream
74+
$proc->stdout->on(
75+
'end',
76+
function () use (&$result) {
77+
$result->resolve(true);
78+
}
79+
);
80+
81+
// handle unsuccessful closure of process stream
82+
$proc->stdout->on(
83+
'close',
84+
function () use (&$result, $process) {
85+
$result->reject(
86+
new \Exception(
87+
\sprintf('Closed process "%s"', $process)
88+
)
89+
);
90+
}
91+
);
92+
93+
return $result->promise();
5194
}

‎tests/AsyncTest.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ public function asyncifyProvider(): array
2424
'(function (...$args) { if (!\is_file($args[0])) { throw new \Exception("Could not find file: " . $args[0]); } return \file_get_contents($file); })',
2525
[12],
2626
],
27-
'Exception: Could not find file: 12',
27+
'Could not find file: 12',
2828
],
2929
// native PHP function
3030
[
3131
['file_get_contents', ['foo.txt']],
3232
concat(
3333
' ',
34-
'Exception: file_get_contents(foo.txt):',
34+
'file_get_contents(foo.txt):',
3535
PHP_VERSION_ID >= 80000 ? 'Failed' : 'failed',
3636
'to open stream: No such file or directory'
3737
),
@@ -41,7 +41,7 @@ public function asyncifyProvider(): array
4141
['file_get_contents', []],
4242
concat(
4343
' ',
44-
'Exception: file_get_contents() expects at least 1',
44+
'file_get_contents() expects at least 1',
4545
PHP_VERSION_ID >= 80000 ? 'argument,' : 'parameter,',
4646
'0 given'
4747
),
@@ -52,7 +52,7 @@ public function asyncifyProvider(): array
5252
'(function ($file) { if (!\is_file($file)) { trigger_error("Could not find file " . $file); } return \file_get_contents($file); })',
5353
['foo.txt'],
5454
],
55-
'Exception: Could not find file foo.txt',
55+
'Could not find file foo.txt',
5656
],
5757
// check if objects can be passed
5858
[

‎tests/Internal/InternalTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function procProvider(): array
2020
// php commandline process
2121
[['php -r \'echo "foo";\''], 'foo'],
2222
// invalid input
23-
[['kat --foo'], ''],
23+
[['kat --foo'], 'Closed process "kat --foo"'],
2424
];
2525
}
2626

0 commit comments

Comments
 (0)
Please sign in to comment.