sleep (あるいは LWP::UserAgent などのそのほかのブロックする処理) をすると、たとえコールバック内でも nonblocking では処理されない。
$http_request_cb で sleep しているこの例は blocking で、 sleep を消せば nonblocking になる。ブロックさせたくない場合は timer を使う。
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Encode;
use AnyEvent;
use AnyEvent::HTTP;
use AnyEvent::Socket;
use AnyEvent::Handle;
use Data::Dumper;
use XML::Simple;
my $server = get_alertinfo();
my $http_request_cb; $http_request_cb = sub {
my ($body, $hdr) =@_;
my $xml = XMLin(decode_utf8 $body);
print Dumper $xml->{request_id};
sleep 5;
};
my $socket_read_cb; $socket_read_cb = sub {
my ($handle, $chat_tag) = @_;
$chat_tag = XMLin(decode_utf8 $chat_tag);
if (defined $chat_tag->{content}) {
my ($lv_num, $co_num, $user_id) = split/,/, $chat_tag->{content};
if (defined $lv_num && defined $co_num && defined $user_id) {
print Dumper $lv_num;
my $url = 'http://live.nicovideo.jp/api/getstreaminfo/lv';
http_request(
GET => "$url$lv_num",
timeout => 3,
$http_request_cb
);
}
}
$handle->push_read(line => "\0", $socket_read_cb);
};
my $connection_cb; $connection_cb = sub {
my ($fh) = @_ or die $!;
my $thread_tag_attr = {
thread => $server->{thread},
res_from => '-1',
version => '20061206',
};
my $thread_tag = XMLout($thread_tag_attr, RootName => 'thread') . "\0";
my $handle; $handle = new AnyEvent::Handle(
fh => $fh,
on_error => sub {
warn "Error $_[2]\n";
$_[0]->destroy;
},
on_eof => sub {
$handle->destroy;
warn "Done\n";
}
);
$handle->push_write($thread_tag);
$handle->push_read(line => "\0", $socket_read_cb);
};
my $cv = AE::cv;
my $connection = tcp_connect(
$server->{addr}, $server->{port}, $connection_cb,
);
$cv->recv;
sub get_alertinfo {
my $url = 'http://live.nicovideo.jp/api/getalertinfo';
use LWP::UserAgent;
my $ua = LWP::UserAgent->new();
my $res = $ua->get($url);
die $res->status_line unless $res->is_success;
my $xml = XMLin($res->decoded_content);
die "Fatal: Server status $xml->{status}" if $xml->{status} ne 'ok';
return $xml->{ms};
}