m6w6 / ext-pq

PostgreSQL client library (libpq) binding
BSD 2-Clause "Simplified" License
39 stars 7 forks source link

pq\Connection::listen - require polling? #8

Closed ParkFramework closed 8 years ago

ParkFramework commented 8 years ago

This does not work:

$conn1 = new pq\Connection($dsn);
$conn1->listen("queue", function($channel, $message, $backend_pid) {
    echo $message;
});

$conn2 = new pq\Connection($dsn);
$conn2->notify("queue", "Hello World!");

That's work, if send any query $conn1->exec(';') after $conn2->notify

$conn1 = new pq\Connection($dsn);
$conn1->listen("queue", function($channel, $message, $backend_pid) {
    echo $message;
});

$conn2 = new pq\Connection($dsn);
$conn2->notify("queue", "Hello World!");

$conn1->exec(';');

This is a bug or so conceived? I need async event-loop without polling, like pub/sub in Redis :)

m6w6 commented 8 years ago

Yes, unfortunately, this is how it works in PostgreSQL, you have to perform some action to get notified.

Thanks.

EDIT: Actually I just read the last paragraph again in the lipq docs:

A better way to check for NOTIFY messages when you have no useful commands to execute is to call PQconsumeInput, then check PQnotifies. You can use select() to wait for data to arrive from the server, thereby using no CPU power unless there is something to do. (See PQsocket to obtain the file descriptor number to use with select().) Note that this will work OK whether you submit commands with PQsendQuery/PQgetResult or simply use PQexec. You should, however, remember to check PQnotifies after each PQgetResult or PQexec, to see if any notifications came in during the processing of the command.

That would mean we have to select() on Connection::$socket and use Connection::poll(). I gotta have to check, how that works out!

Thanks.

m6w6 commented 8 years ago

So e.g.

$r[] = $conn1->socket;
$w = $e = null;

while (stream_select($r, $w, $e, 1)) {
    $conn1->poll();
}
ParkFramework commented 8 years ago

I understand, but stream_select() blocking $tv_sec PHP script.

We need to run at the time of polling of our inactivity event-loop swoole_server I'll try to add $conn1->socket to a common event-loop https://rawgit.com/tchiotludo/swoole-ide-helper/english/docs/classes/swoole_server.html#method_bind

P.S. Our use case: notification to PHP client for invalidate cache, this is a very interesting task :)

m6w6 commented 8 years ago

Hey! stream_select does not necessarily block, set the timeout to 0 (zero) to let it return immediately:

$r = [$conn->socket];
if (stream_select($r,$w,$e,0)) {
    $conn->poll();
}

Hope this helps!

ParkFramework commented 8 years ago

Yes i know.

Zero timeout is useful if the message has come, new messages in real time would like to have in the common event-loop swoole_server.

Anyway, thanks.