symplely / processor
An Symfony Process Manager offering Parallel and asynchronous PHP for Blocking I/O.
Installs: 1 656
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Requires
- php: >7.2
- opis/closure: ^3.5.1
- symfony/process: ^5.0.4
Requires (Dev)
- phpunit/phpunit: ^6 | ^7 | ^8
README
An simply process manager wrapper API for symfony/process to execute and manage sub-processes.
It's an alternative to pcntl-extension, when not installed. This is part of our symplely/coroutine package for handling any blocking i/o process not handle by Coroutine natively.
The library is to provide an easy to use API to control/manage sub processes for windows OS, and other systems, without any additional software extensions installed.
Installation
composer require symplely/processor
Usage
include 'vendor/autoload.php'; use Async\Processor\Processor; // To set the path to PHP executable for child process Processor::phpPath('/some/path/version-7.3/bin/php'); $process = \spawn($function, $timeout, $channel) // Or $process = Processor::create(function () use ($thing) { // Do a thing }, $timeout, $channel) ->then(function ($output) { // Handle success })->catch(function (\Throwable $exception) { // Handle exception }); \spawn_run($process); // Or $process->run(); // Second option can be used to set to display child output, default is false \spawn_run($process, true); // Or $process->displayOn()->run();
Channel - Transfer messages between a Process
include 'vendor/autoload.php'; use Async\Processor\Channel; use Async\Processor\ChannelInterface; $ipc = new Channel(); $process = spawn(function (ChannelInterface $channel) { $channel->write('ping'); // same as echo 'ping' or echo fwrite(STDOUT, 'ping') usleep(1000); echo $channel->read(); // same as echo fgets(STDIN); echo $channel->read(); usleep(1000); return 'return whatever'; }, 300, $ipc) ->progress(function ($type, $data) use ($ipc) { if ('ping' === $data) { $ipc->send('pang' . \PHP_EOL); } elseif (!$ipc->isClosed()) { $ipc->send('pong' . \PHP_EOL); ->close(); } }); $ipc->setup($process) \spawn_run($process); echo \spawn_output($process); // pingpangpongreturn whatever // Or echo $ipc->receive(); // return whatever
Event hooks
When creating asynchronous processes, you'll get an instance of LauncherInterface
returned.
You can add the following event hooks on a process.
$process = spawn($function, $timeout, $channel) // Or $process = Processor::create(function () { // The second argument is optional, Defaults 300. // it sets The maximum amount of time a process may take to finish in seconds // The third is optional input pipe to pass to subprocess }, int $timeout = 300 , $input = null) ->then(function ($output) { // On success, `$output` is returned by the process. }) ->catch(function ($exception) { // When an exception is thrown from within a process, it's caught and passed here. }) ->timeout(function () { // When an time is reached, it's caught and passed here. }) ->progress(function ($type, $data) { // A IPC like gateway: `$type, $data` is returned by the process progressing, it's producing output. // This can be use as a IPC handler for real time interaction. });
There also ->done
, part of ->then()
extended callback method.
->done(function ($result) { // On success, `$result` is returned by the process or callable you passed to the queue. }); ->then(function ($resultOutput) { // }, function ($catchException) { // }, function ($progressOutput) { // } ); // To turn on to display child output. ->displayOn(); // Stop displaying child output. ->displayOff(); // To display child output, only by third party means once turned on. ->display(); // Processes can be retried. ->restart(); ->run();
Error handling
If an Exception
or Error
is thrown from within a child process, it can be caught per process by specifying a callback in the ->catch()
method.
If there's no error handler added, the error will be thrown in the parent process when calling spawn_run()
or $process->run()
.
If the child process would unexpectedly stop without throwing an Throwable
, the output written to stderr
will be wrapped and thrown as Async\Processor\ProcessorError
in the parent process.
Contributing
Contributions are encouraged and welcome; I am always happy to get feedback or pull requests on Github :) Create Github Issues for bugs and new features and comment on the ones you are interested in.
License
The MIT License (MIT). Please see License File for more information.