The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Manager;

=pod

This is an extended example of how to reap child workers if this
parent manager process receives a TERM signal.

=cut

use Moose;
with qw(MooseX::Workers);

use lib ".";

#sub POE::Kernel::ASSERT_DEFAULT () { 1 }
#sub POE::Kernel::TRACE_SIGNALS ()  { 1 }
use POE::Session; # Get export constants like KERNEL, HEAP, STATE etc

use Getopt::Long;
use Pod::Usage;

use Data::Dumper;

my $debug       = 0;
my $help        = 0;
my $num_workers = 4;

my @argv = @ARGV;

GetOptions(
    'debug|d'       => \$debug,
    'help|?'        => \$help,
    'num_workers=i' => \$num_workers,
);

pod2usage(1) if $help;
$ENV{CATALYST_DEBUG} = 1 if $debug;

sub run {
	my $self  = shift;

	for my $i (1..$num_workers) {
		$self->spawn( sub {
		    require App;
		    App->run();
		} );
	}

        POE::Kernel->run();
}

sub process_output {
	my ($debug, $worker_id) = @_;
	printf "[%02d] %s\n", $worker_id, $debug;
}

# Implement our Interface
sub worker_manager_start { warn "started worker manager: \n" }
sub worker_manager_stop  {
    my ($self) = shift;

    $self->_kill_workers();

    warn 'stopped worker manager'
}

sub _kill_workers {
    my ($self, @args) = shift;

    my @keys = $self->get_worker_ids;

    foreach my $wheel_id ( @keys ) {
	warn "going to kill_worker($wheel_id)\n";
	$self->kill_worker($wheel_id);
    }
 
}

sub max_workers_reached  { warn 'maximum worker count reached' }

sub worker_stdout  { shift; process_output(@_) }
sub worker_stderr  { shift; process_output(@_) }
sub worker_error   { shift; warn join ' ', @_; }
sub worker_finished    {
	my $self = shift;
	process_output('restarting...', 0);
	$self->spawn( sub { 
			      require App;
			      App->run();
		      } );
}
sub worker_started { shift; process_output("Worker $_[0] started", 0) }
sub sig_child      { shift; process_output("Worker $_[0] exited with signal $_[1]", 0) }

sub sig_TERM {
    my ($self) = @_;
    $self->_kill_workers();
    $self->num_workers = 0; # worker_finished() would restart them otherwise
}

no Moose;

my $manager = Manager->new();
$manager->run();

print "Done\n";