jaxwilko/weird-php

通过子进程实现异步PHP

v0.0.6 2024-07-31 11:14 UTC

This package is auto-updated.

Last update: 2024-08-31 11:31:31 UTC


README

该项目旨在通过在多个进程中分配任务来为PHP添加异步支持。

要求

Weird需要

  • PHP >= 8.2
  • 访问pcntl方法(proc_openproc_get_statusproc_terminate

安装

composer require jaxwilko/weird-php

使用

默认情况下,Weird与Promise类一起工作,您也可以传递可调用参数,但您不会从它们那里收到输出。

use Weird\Promise;

Promise::make(function (Thread $thread) {
    // do some really cool stuff
    $result = 'Hello world';
    return $result;
})
    ->then(function (string $result) {
        echo $result;
        // Prints: Hello World
    })
    ->catch(function (\Throwable $e) {
        // This will catch any exceptions happening parent process, not the child process.
    })

使用ProcessManager,我们可以将多个进程分配到我们想要的任意数量的进程中。

use Weird\ProcessManager;
use Weird\Processes\Thread;
use Weird\Promise;

$manager = ProcessManager::create()
    ->spawn(Thread::class, processes: 1);

$manager->dispatch([
    // Promise 1
    Promise::make(function () {
        return 'hello';
    })->then(fn ($str) => $str . ' world')
        ->then(fn ($str) => echo $str . PHP_EOL),

    // Promise 2
    Promise::make(function () {
        return 'world';
    })->then(fn ($str) => $str . ' hello')
        ->then(fn ($str) => echo $str . PHP_EOL)
]);

当创建一个新的进程时,它将失去对当前全局作用域的访问权限,这意味着诸如您的自动加载器之类的工具将不会加载。默认情况下,如果找到,Weird将尝试加载您的composer自动加载文件。或者,您可以通过withBootstrap()方法提供要注册自动加载器的文件。

$manager = ProcessManager::create()
    ->withBootstrap(__DIR__ . '/vendor/autoload.php')
    ->spawn(Thread::class);

由于这些进程是异步运行的,如果您想处理它们,您需要告诉进程管理器何时检查它们。要等待所有活动进程完成,请调用wait()。等待还接受一个超时参数,该参数为秒的浮点数。

$manager = ProcessManager::create()
    ->spawn(Thread::class, processes: 1);

$manager->dispatch(function () {
    // do something
});

$manager->wait(timeout: 0.5);

或者,您可以手动调用tick()函数,该函数将检查由子进程返回的承诺并进行处理。

$manager = ProcessManager::create()
    ->spawn(Thread::class, processes: 1);

$manager->dispatch(
    Promise::make(function () {
        // do something
    })->then(function (string $output) {
        // do something else
    })
);

while ($doingSomethingElse) {
    // ...
    $manager->tick();
    // ...
}

提示

提示是从一个进程发送的特殊消息,可以提供有关正在发生什么的反馈。

要发送一个提示,您可以调用方法\Weird\Messages\Events\Hint::send($message)

可以在ProcessManager对象上调用registerHintHandler()来注册一个提示处理程序。

$manager->registerHintHandler(function (mixed $message, Process $process) {
    echo $message;
});

UnknownMessage

由于Weird如何监听输出流,通过直接向缓冲区输出发送的任何数据都将被捕获为UnknownMessage。可以通过在ProcessManager对象上调用registerUnknownMessageHandler()来监听这些。

$manager->registerUnknownMessageHandler(function (mixed $message, Process $process) {
    echo $message;
});

进程

在Weird中包含的Thread进程允许您执行多个异步PHP操作。本文档的大部分内容概述了Thread的使用,但是您可以实现自己的ParallelProcess类,并用ProcessManager来启动它。

例如

class MyCustomProcess extends \Weird\Processes\ParallelProcess
{
    // Define how often tick should be executed in seconds
    protected float $tickRate = 1 / 32;

    public function register()
    {
        // execute startup tasks
    }

    public function read($stdin)
    {
        while ($message = $this->readStream($stdin)) {
            // do something with messages sent from the parent process
        }
    }

    public function tick()
    {
        // do something
    }
}

// ...

$manager = ProcessManager::create()
    ->spawn(MyCustomProcess::class, processes: 5);