立即收到邮政通知的通知



DBD::P g有什么方法可以阻止等待消息准备就绪时立即返回的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),以便它不是一个繁忙的循环,但当然这意味着我在发送 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 提供了一种避免轮询循环的方法,但我似乎无法在没有轮询循环的情况下使其工作。 建议?

问题是 $read_set 可能在第一次 select(( 调用后就被毁了。您应该将其替换为以下内容:

select(my $read_out = $read_set, undef, undef, 10);

在第一次调用之后,您可能还不会收到通知,因此您会返回一个空的 fd 集,下次使用空集调用 select 时,这就是为什么您需要将 $read_set 复制到不同的变量中。

相关内容

  • 没有找到相关文章

最新更新