Skip to content

Instantly share code, notes, and snippets.

@klopp
Last active May 6, 2016 19:46
Show Gist options
  • Save klopp/975e2e3917f68999f615097c1e13060f to your computer and use it in GitHub Desktop.
Save klopp/975e2e3917f68999f615097c1e13060f to your computer and use it in GitHub Desktop.
Тестовое задание
#!/usr/bin/perl
# ------------------------------------------------------------------------------
# Необходимо разработать консольное приложение на базе фреймворка AnyEvent,
# которое принимает список URL из STDIN, вызывает их все сразу в
# неблокирующем режиме, выводя на экран полученные ответы по мере их получения
# и статистику по скорости вызова каждого урла после завершения всех вызовов.
# ------------------------------------------------------------------------------
use Modern::Perl;
use AnyEvent::Fork;
use AnyEvent::Fork::Pool;
# ------------------------------------------------------------------------------
use constant DEBUG => 1;
# ------------------------------------------------------------------------------
my @links;
if (DEBUG) {
@links
= qw{ http://ya.ru/ http://google.ru/ http://goo.gl/ http://yandex.ru/ };
}
else {
@links = grep { s/^\s+|\s+$//gs; $_ } <STDIN>;
}
# ------------------------------------------------------------------------------
my %stat;
my $workers = @links;
# Хотя, можно и так:
# my $workers = AnyEvent::Fork::Pool::ncpu 1;
# Не самый удачный вариант с eval. Но тут кода мало, и просто не хочется
# создавать отдельный модуль в отдельном файле для require:
my $pool = AnyEvent::Fork->new()->eval('
sub _get_url {
# На входе URL, на выходе - время его закачки.
# Ошибки игнорируем.
my ( $url ) = @_;
use Modern::Perl;
use AnyEvent::HTTP;
use Time::HiRes qw/gettimeofday tv_interval/;
my $tstart = [gettimeofday];
my $cv = AnyEvent->condvar;
http_get $url, sub {
my ($body, $hdr) = @_;
say $url, q{, status: }, $hdr->{Status};
$cv->send;
};
$cv->recv;
my $tend = [gettimeofday];
return tv_interval($tstart, $tend);
}')->AnyEvent::Fork::Pool::run('_get_url', max => $workers);
my $cv = AnyEvent->condvar;
my $done = 0;
for my $url (@links) {
$pool->(
$url,
sub {
$stat{$url} = $_[0];
$done++;
$cv->send if $done >= $workers;
}
);
}
$cv->recv;
say q{};
for (sort { $stat{$a} <=> $stat{$b} } keys %stat) {
say "$_ : $stat{$_} sec";
}
# ------------------------------------------------------------------------------
# That's All, Folks!
# ------------------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment