amphp / postgres

Async Postgres client for PHP based on Amp.
MIT License
97 stars 20 forks source link

Closing connection during a long running query blocks the loop #53

Closed oleg1540 closed 1 year ago

oleg1540 commented 2 years ago

If we have a long running query and try to close connection while it is executing, loop will be blocked.

Script:

<?php

use Amp\Loop;
use Amp\Postgres\ConnectionConfig;
use function Amp\Postgres\pool;

require __DIR__ . '/../vendor/autoload.php';

Loop::run(function () {
    echo 'Start' . PHP_EOL;

    $config = ConnectionConfig::fromString("host=localhost user=test password=1234 db=test");
    $pool = pool($config);

    Loop::repeat(1000, static function () {
        echo 'Loop heartbeat: ' . time() . PHP_EOL;
    });

    Loop::delay(3000, static function () use ($pool) {
        echo 'Close connection' . PHP_EOL;
        $pool->close();
    });

    try {
        echo 'Query' . PHP_EOL;
        $result = yield $pool->execute('SELECT pg_sleep(10)');
        while (yield $result->advance()) {
            $row = $result->getCurrent();
            var_dump($row);
        }
    } catch (Throwable $e) {
        echo $e->getMessage() . PHP_EOL;
    }
});

Result:

Start Query Loop heartbeat: 1661195555 Loop heartbeat: 1661195556 Close connection The connection was closed Loop heartbeat: 1661195564 Loop heartbeat: 1661195565 Loop heartbeat: 1661195566 Loop heartbeat: 1661195567

Loop was blocking for 8 seconds from 1661195556 to 1661195564 until query end. Is it expected behavoir?

Seems, loop must not be blocked in this case.

oleg1540 commented 2 years ago

Try to cancel query before pg_close() in src/PgSqlHandle.php::close().

Start Query Loop heartbeat: 1661196633 Loop heartbeat: 1661196634 Close connection The connection was closed Loop heartbeat: 1661196635 Loop heartbeat: 1661196636 Loop heartbeat: 1661196637 Loop heartbeat: 1661196638

trowski commented 1 year ago

54 has been merged and tagged under v1.4.5.