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};
}