App-Ringleader
view release on metacpan or search on metacpan
lib/App/Ringleader.pm view on Meta::CPAN
has inactivity_delay => (
is => 'ro',
isa => 'Int',
lazy => 1,
default => sub {
60 * ( $_[0]->configuration->{inactivity_delay} || 60 );
},
);
has services => (
is => 'ro',
lazy => 1,
default => sub {
my $services = $_[0]->configuration->{services};
$_ = Ubic->service($_) for values %$services;
return $services;
},
);
has cache => (
is => 'ro',
lazy => 1,
default => sub {
return CHI->new(
%{ $_[0]->configuration->{CHI}
|| { driver => 'FastMmap' } }
);
},
);
sub run {
my $self = shift;
my $proxy = HTTP::Proxy->new( host => undef, port => $self->port );
$proxy->push_filter(
request => HTTP::Proxy::HeaderFilter::simple->new( sub {
my( undef, undef, $request ) = @_;
my $uri = $request->uri;
my $host = $uri->host;
my $service = $self->services->{ $host } or die;
$uri->host( 'localhost' );
$uri->port( $service->port );
unless ( $self->cache->get($host) ) {
$service->start;
sleep 1;
}
# always store the latest access time
$self->cache->set( $host => time );
})
);
$self->start_monitor;
say 'ringleader started...';
$proxy->start;
}
sub start_monitor {
my $self = shift;
return if fork;
while( sleep $self->inactivity_delay ) {
$self->check_activity_for( $_ ) for keys %{ $self->services };
}
}
sub check_activity_for {
my( $self, $s ) = @_;
my $time = $self->cache->get($s);
# no cache? assume not running
return if !$time or time - $time <= $self->inactivity_delay;
$self->services->{$s}->stop;
$self->cache->remove($s);
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
App::Ringleader - Proxy for sproradically-used web application
=head1 VERSION
version 0.1.0
=head1 SYNOPSIS
use App::Ringleader;
App::Ringleader->new( conf => 'ringleader.yml' )->run;
=head1 DESCRIPTION
Ringleader is a proxy that will wake up psgi applications upon request
and shut them down after a period of inactivity. It's meant to provide a
middle-ground between the slowliness of CGI and the constant resource
consumption of plack applications for services that are not often used.
Typically, you'll use it via the C<ringleader> script.
Ringleader relies on L<Ubic> to start and stop the services. For PSGI
applications, you probably want to define your services using
( run in 0.432 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )