DBD::Pg 有什么方法可以阻塞等待消息准备就绪时立即返回的 NOTIFY?
我有一个简单的测试脚本,可以使用 Postgres 的“通知”机制发送消息:
#!/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)
它以便它不是一个繁忙的循环,但这当然意味着我在发送 NOTIFY 消息后但在我的 LISTEN 接收到它之前得到长达 10 秒的延迟。
一些搜索建议在libpq
级别上,您可以select
在套接字上执行一个以立即收到传入通知的通知,所以我尝试了这个:
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 提供了一种避免轮询循环的方法,但我似乎无法在没有轮询循环的情况下使其工作。建议?