Есть ли способ с DBD :: Pg сделать блокировку ожидания для NOTIFY, который немедленно вернется, когда сообщение будет готово?
У меня есть простой тестовый скрипт, который может отправлять сообщения, используя механизм Postgres NOTIFY:
#!/usr/bin/perl
use 5.018;
use strict;
use warnings;
use autodie;
use DBI qw();
$| = 1; # Flush buffer on print
my $dsn = 'dbi:Pg:dbname=test';
my $attr = {
AutoCommit => 0,
RaiseError => 1,
PrintError => 0,
};
my $topic = 'test_topic';
my $dbh = DBI->connect($dsn, '', '', $attr);
while (1) {
print "payload: ";
chomp(my $payload = <>);
$dbh->do("NOTIFY $topic, '$payload'");
$dbh->commit;
}
У меня также есть простой скрипт-получатель, который использует LISTEN для подписки на сообщения:
#!/usr/bin/perl
use 5.018;
use strict;
use warnings;
use autodie;
use DBI qw();
$| = 1; # Flush buffer on print
my $dsn = 'dbi:Pg:dbname=test';
my $attr = {
AutoCommit => 0,
RaiseError => 1,
PrintError => 0,
};
my $topic = 'test_topic';
my $dbh = DBI->connect($dsn, '', '', $attr);
$dbh->do("LISTEN $topic");
while (1) {
$dbh->commit();
while(my $notify = $dbh->pg_notifies) {
my($topic, $pid, $payload) = @$notify;
say "Got message: $topic => $payload";
}
sleep(10);
}
Проблема в том, что $dbh->pg_notifies
не блокируется, поэтому, если в очереди нет уведомлений, немедленно возвращается undef
. Я поставил sleep(10)
, чтобы он не был занятым, но, конечно, это означает, что я получаю задержку до 10 секунд после отправки сообщения NOTIFY, но до того, как мой LISTEN его получит.
Некоторые поиски показали, что на уровне libpq
вы могли бы сделать select
в сокете, чтобы немедленно получить уведомление о входящем NOTIFY, поэтому я попробовал это:
my $sock_fd = $dbh->{pg_socket};
my $read_set = '';
vec($read_set, $sock_fd, 1) = 1;
while (1) {
$dbh->commit();
while(my $notify = $dbh->pg_notifies) {
my($topic, $pid, $payload) = @$notify;
say "Got message: $topic => $payload";
}
select($read_set, undef, undef, 10);
}
Но, похоже, он не работает, и select
, кажется, возвращается только тогда, когда истекает мой 10-секундный тайм-аут.
Мне всегда казалось, что NOTIFY / LISTEN предоставляет способ избежать циклов опроса, но я не могу заставить его работать без цикла опроса. Предложения?