Skip to content

Instantly share code, notes, and snippets.

@wchristian
Created November 3, 2010 16:49
Show Gist options
  • Save wchristian/661341 to your computer and use it in GitHub Desktop.
Save wchristian/661341 to your computer and use it in GitHub Desktop.
use strict;
use warnings;
package Parallel::Downloader;
use Moose;
use MooseX::HasDefaults::RO;
has requests => ( isa => 'ArrayRef', required => 1 );
has responses => ( isa => 'ArrayRef', default => sub {[]} );
has workers => ( isa => 'Int', default => 10 );
has cv => ( isa => 'AnyEvent::CondVar', default => sub { AnyEvent->condvar } );
has aehttp_args => ( isa => 'HashRef', default => sub{{}} );
has debug => ( isa => 'Bool', default => 1 );
has logger => ( isa => 'CodeRef', default => sub { \&_default_log } );
use AnyEvent::HTTP;
sub run {
my ( $self ) = @_;
return if !@{$self->requests};
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};
}
sub add_request {
my ( $self, $worker_id ) = @_;
return $self->end_worker( $worker_id ) if !@{$self->requests};
my $req = shift @{$self->requests};
my $post_run = sub {
push @{$self->responses}, [ @_, $req ];
$self->add_request( $worker_id );
};
http_request(
$req->method,
$req->uri->as_string,
body => $req->content,
%{$self->aehttp_args},
$post_run
);
$self->log( msg => "$worker_id accepted new request", type => "WorkerAddRequest", worker_id => $worker_id, req => $req );
return;
}
sub end_worker {
my ( $self, $worker_id ) = @_;
$self->log( msg => "$worker_id ended", type => "WorkerEnd", worker_id => $worker_id );
$self->cv->end;
return;
}
sub sanitize_worker_max {
my ( $self ) = @_;
die "max should be 0 or more" if $self->workers < 0;
my $request_count = @{$self->requests};
return $request_count if !$self->workers; # 0 = as many parallel as possible
return $request_count if $self->workers > $request_count; # not more than the request count
return $self->workers;
}
sub log {
my ( $self, %msg ) = @_;
return $self->logger->( $self, \%msg );
}
sub _default_log {
my ( $self, $msg ) = @_;
return if !$self->debug;
print "$msg->{msg}\n";
return;
}
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment