walkor / workerman

An asynchronous event driven PHP socket framework. Supports HTTP, Websocket, SSL and other custom protocols.
http://www.workerman.net
MIT License
11.03k stars 2.25k forks source link

[question] Can we use Timer::add(0, $func, $vars, false) to run tasks async #937

Open joanhey opened 1 year ago

joanhey commented 1 year ago

Hi, I have seen that in other frameworks, in reality is the base of async.

Timer::add(0, $func, $vars, false); Theoretically this task will be included to schedule in the event loop. If so, perhaps it will be better to add a Timer::once(0, $func, $vars);.

Example: Timer::add(0, $send_mail, $vars, false);

What do you think @walkor ??

walkor commented 1 year ago

I'm not sure if all the drivers (event, Uv, revolt, swoole, etc.) support passing 0 as the timer value. If they do, Workerman should indeed support it as well.

xpader commented 1 year ago

I think that name is defer.

joanhey commented 11 months ago

With 0 or 0.0, return Exception: bad time_interval (using select event).

Now I'm testing with Adapterman and Symfony $kernel->terminate, and for now seems that it's working.

function run(): string
{
    global $kernel;

    ob_start();

    $request = Request::createFromGlobals();
    $response = $kernel->handle($request);
    $response->send();

    Timer::add(0.001, function () use ($kernel, $request, $response) {
        $kernel->terminate($request, $response);
    }, persistent: false);

    //$kernel->terminate($request, $response);

    return ob_get_clean();
}
joanhey commented 10 months ago

Example with Adapterman and Symfony.

Using Timer to defer $kernel->terminate($request, $response);

Timer::add(0.001, function () use ($kernel, $request, $response) {
        $kernel->terminate($request, $response);
    }, persistent: false);

//$kernel->terminate($request, $response);

Without defer, run inmediatelly:

image image

With defer, run after enter in the event loop:

image

image

The data to create the graph, it's sent in the kernel.terminate.

joanhey commented 10 months ago

To show the requests with time used with Adapterman (or Workerman) live in the terminal, it's as simple as:

 $http_worker->onMessage = static function ($connection, $request) {

    $start = microtime(true);
    $connection->send(run());
    Worker::safeEcho($_SERVER['REQUEST_METHOD'] ."\t". $_SERVER['REQUEST_URI'] ."\t". round((microtime(1) - $start) * 1000, 4) . ' ms' . PHP_EOL);
};