LWP::UserAgent 获取超时回调

LWP::UserAgent get callback with timeout

如果时间到了(2 秒),是否丢失了此代码的块,还是 get 重试下载丢失的块?

use LWP::UserAgent;

my $url = '...';
my $file_name = '...';
my $ua = LWP::UserAgent->new();

open my $fh, '>>:raw', $file_name or die $!;
my $res = $ua->get( 
    $url,
    ':content_cb' => sub {
        my ( $chunk, $res, $proto ) = @_;
        eval {
            local $SIG{ALRM} = sub { die "time out\n" };
            alarm 2;
            print $fh $chunk;
            alarm 0;
        };
        # ...
    },
);
close $fh;

如果为一个块调用了'content_cb'回调,那么这意味着该块已经从请求中成功返回。 LWP::UserAgent 层在那个时候完成了它的工作(相对于那个块)。然后你的程序负责对块做任何事情。 LWP::UserAgent 不知道您的程序如何设置或处理系统信号,因此它不可能重做任何请求,或重新通知您的程序任何块,以响应系统信号或发生的任何其他事件在您的程序上下文中打开(并且在 LPW::UserAgent 的上下文之外)。

另外需要说明的是,即使你设置了LWP::UserAgenttimeout属性,它也适用于pending serveractivity(比如响应请求根本没有,或者发送下一个块),那么 LWP::UserAgent 在这种超时的情况下甚至不会重新发送请求。该模块根本就没有设计成在任何情况下都能做到这一点:

The requests is aborted if no activity on the connection to the server is observed for timeout seconds.

如果发生任何类型的超时,或者如果您的代码认为它没有从服务器收到足够的响应数据,您总是可以在您的代码中重新发送请求。

如果您担心超时,请使用 timeout method。 在您的代码中,当一大块数据到达时,LWP::UserAgent 会调用您的 ':content_cb' 回调,并且不会重试。

IMO 以这种方式处理超时是没有意义的,因为它永远不会发生(除非 print $fh $chunk; 花时间)。