amphp / amp

A non-blocking concurrency framework for PHP applications. 🐘

Home Page:https://amphp.org/amp

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Promise timeout with loop defer function

Tiadem opened this issue · comments

Hello i'm new to this project and don't really creating that much of github issues overall,so feel free to correct me. Is it posible to timeout processes written in standard PHP code (doSomething function will make bunch of operations linked with web scrapping ultimately). I've tested this simple problem with sleep and it didn't work. Only possible way to trigger TimeoutException was by using Loop's delay function.

use Amp\Deferred;
use Amp\Loop;

use function Amp\Promise\timeout;

require_once __DIR__ ."/vendor/autoload.php";

function doSomething($def)
{
    Loop::defer(function ()  use ($def){
        sleep(3);
        $def->resolve('Done.');
    });
}

Loop::run(function () {
    $deferred = new Deferred();
    $promise = $deferred->promise();
    timeout($promise,2000);
    doSomething($deferred);
    $promise->onResolve(function (Throwable $error = null, $result = null) {
        if ($error) {
            printf(
                "Something went wrong:\n%s\n",
                $error->getMessage()
            );
        } else {
            printf(
                "Hurray! Our result is:\n%s\n",
                print_r($result, true)
            );
        }
    });

});

Hey @Tiadem, welcome! As you have observed, timeout doesn't work with sleep. That's because it's a blocking function that blocks the whole process. In fact, timeout doesn't cancel any operation either, it's just a way to timeout waiting for a particular promise to resolve.

Try adding another repeat timer that prints some dots periodically and observe the difference with using sleep vs. delay.

Hey @kelunik thanks for support, you guys are doing great job for PHP 😄 . Perhaps i have to dive more into understanding those async, concurrency concepts.At the beginning i assumed that timeout function starts counting from Loop's defer function call till resolve function call. If that process will exceed timeout then exception will be thrown immediately and stops further promise resolving as it's catched. But now i suppose that regular sleep function stops everything including time counting between defer call and resolve call. Is there any example from standard PHP operations that works with timeout or just those Loop delay and repeat functions?

@Tiadem Thanks! sleep doesn't stop the time counting, but it simply blocks the defer callback from executing or rather the event loop checking whether it should execute anything else. Standard PHP functions aren't compatible with the event loop without special care, e.g. streams need to be set to non-blocking mode. That's why we've built to many packages around I/O implementing things in a non-blocking and compatible way.