Parallel-Downloader
view release on metacpan or search on metacpan
lib/Parallel/Downloader.pm view on Meta::CPAN
use strictures;
package Parallel::Downloader;
our $VERSION = '0.132071'; # VERSION
# ABSTRACT: simply download multiple files at once
#
# This file is part of Parallel-Downloader
#
#
# Christian Walde has dedicated the work to the Commons by waiving all of his
# or her rights to the work worldwide under copyright law and all related or
# neighboring legal rights he or she had in the work, to the extent allowable by
# law.
#
# Works under CC0 do not require attribution. When citing the work, you should
# not imply endorsement by the author.
#
use Moo;
use MooX::Types::MooseLike::Base qw( Bool Int HashRef CodeRef ArrayRef );
sub {
has requests => ( is => 'ro', isa => ArrayRef, required => 1 );
has workers => ( is => 'ro', isa => Int, default => sub { 10 } );
has conns_per_host => ( is => 'ro', isa => Int, default => sub { 4 } );
has aehttp_args => ( is => 'ro', isa => HashRef, default => sub { {} } );
has debug => ( is => 'ro', isa => Bool, default => sub { 0 } );
has logger => ( is => 'ro', isa => CodeRef, default => sub { \&_default_log } );
has build_response => ( is => 'ro', isa => CodeRef, default => sub { \&_default_build_response } );
has sorted => ( is => 'ro', isa => Bool, default => sub { 1 } );
has _consumables => ( is => 'lazy', isa => ArrayRef, builder => '_requests_interleaved_by_host' );
has _responses => ( is => 'ro', isa => ArrayRef, default => sub { [] } );
has _cv => ( is => 'ro', isa => sub { $_[0]->isa( 'AnyEvent::CondVar' ) }, default => sub { AnyEvent->condvar } );
}
->();
use AnyEvent::HTTP;
use Sub::Exporter::Simple 'async_download';
sub async_download {
return __PACKAGE__->new( @_ )->run;
}
sub _requests_interleaved_by_host {
my ( $self, $requests ) = @_;
my %hosts;
for ( @{ $self->requests } ) {
my $host_name = $_->uri->host;
my $host = $hosts{$host_name} ||= [];
push @{$host}, $_;
}
my @interleaved_list;
while ( keys %hosts ) {
push @interleaved_list, shift @{$_} for values %hosts;
for ( keys %hosts ) {
next if @{ $hosts{$_} };
delete $hosts{$_};
}
}
return \@interleaved_list;
}
sub run {
my ( $self ) = @_;
local $AnyEvent::HTTP::MAX_PER_HOST = $self->conns_per_host;
for ( 1 .. $self->_sanitize_worker_max ) {
$self->_cv->begin;
$self->_log( msg => "$_ started", type => "WorkerStart", worker_id => $_ );
$self->_add_request( $_ );
}
$self->_cv->recv;
return @{ $self->_responses } if !$self->sorted;
my %unsorted = map { 0 + $_->[2] => $_ } @{ $self->_responses };
my @sorted = map { $unsorted{ 0 + $_ } } @{ $self->requests };
return @sorted;
}
sub _add_request {
my ( $self, $worker_id ) = @_;
my $req = shift @{ $self->_consumables };
( run in 1.668 second using v1.01-cache-2.11-cpan-39bf76dae61 )