Fugu
view release on metacpan or search on metacpan
lib/Fugu/Proxy.pm view on Meta::CPAN
# Thus the module keeps the Fugu core-Perl load contract, and an
# installation without them still loads it.
use constant {
PORT_RANGE_START => 8080,
PORT_RANGE_END => 8180,
READY_TIMEOUT => 30,
STREAM_CHUNK => 262144, # 256KB
SEND_BUFFER => 1048576, # 1MB
};
# Fugu::Proxy->new(%args):
# cache => $cache a Fugu::Proxy::Cache (required)
# pidfile => $pidfile a Fugu::Pidfile for the child (required)
# store => $store a Fugu::StateFile that holds the port (required)
# logfile => $path where the child's output goes
# log => $logger default: Fugu::Log->default
# ports => [$first, $last] the range to look in
sub new ( $class, %args )
{
for my $required (qw(cache pidfile store)) {
die "$required parameter required"
unless defined $args{$required};
}
my $ports = $args{ports} // [ PORT_RANGE_START, PORT_RANGE_END ];
return bless {
cache => $args{cache},
pidfile => $args{pidfile},
store => $args{store},
logfile => $args{logfile} // '/dev/null',
log => $args{log} // Fugu::Log->default,
ports => $ports,
meta => Fugu::Proxy::Meta->new,
error => undef,
}, $class;
}
# $self->cache:
# Return the cache object.
sub cache ($self)
{
return $self->{cache};
}
# $self->error: the most recent failure.
sub error ($self)
{
return $self->{error};
}
# $self->port:
# Return the port the running proxy listens on, or undef.
sub port ($self)
{
return $self->{store}->get('proxy_port');
}
# $self->is_running:
# Report if the proxy child is alive. The check reaps, so a
# child that became a zombie reads as stopped.
sub is_running ($self)
{
return $self->{pidfile}->is_running ? 1 : 0;
}
# $self->start:
# Start the proxy child and wait until it takes connections. The
# method returns the port, or undef with the reason in ->error.
# A proxy that already runs returns its port and starts nothing.
sub start ($self)
{
$self->{error} = undef;
return $self->port if $self->is_running;
my $port = $self->_find_free_port;
unless ( defined $port ) {
$self->{error} = sprintf 'no free port in %d-%d',
@{ $self->{ports} };
return;
}
my $child = ref $self;
my $result = Fugu::Process->spawn_perl(
code => "use $child; $child->run_child(\@ARGV)",
args => [ $port, $self->{cache}->dir ],
daemonize => 1,
stdout => $self->{logfile},
stderr => $self->{logfile},
);
unless ( $result->{success} ) {
$self->{error} = "cannot start the proxy: $result->{error}";
return;
}
$self->{pidfile}->write_pid( $result->{pid} );
$self->{store}->set( proxy_port => $port );
unless ( $self->wait_ready ) {
$self->{error} = 'the proxy did not take connections';
$self->stop;
return;
}
return $port;
}
# $self->stop:
# Stop the proxy child and forget its port. The method returns 1.
sub stop ($self)
{
my $pid = $self->{pidfile}->read_pid;
Fugu::Process->terminate( $pid, grace_period => 5 )
if defined $pid;
$self->{pidfile}->remove;
$self->{store}->delete('proxy_port');
return 1;
( run in 1.573 second using v1.01-cache-2.11-cpan-14f38c9f855 )