use strict;
use POSIX qw(:sys_wait_h);
use Class::Tiny qw(name instance_id code pid parent_pid), {
id => sub {
my ($self) = @_;
return sprintf '%s.%s', $self->name, $self->instance_id;
}
};
=head1 NAME
Continual::Process::Instance - one instance
=head1 SYNOPSIS
$instance = Continual::Process::Instance->new(
name => 'job1',
instance_id => 1,
code => sub {
...
return $pid;
}
)->start();
while(1) {
if (!$instance->is_alive()) {
$instance->start();
}
}
=head1 DESCRIPTION
This class represents one instance of L<Continual::Process>
=head1 METHODS
=head2 new(%attributes)
=head3 %attributes
=head4 name
name of process
=head4 instance_id
id of instance (number)
=head4 code
CodeRef
=cut
sub BUILD {
my ($self) = @_;
foreach my $req (qw/name instance_id code/) {
die "$req attribute required" if !defined $self->$req;
}
if (ref $self->code ne 'CODE') {
die 'code attribute must be CodeRef';
}
$self->parent_pid($$);
}
=head2 start()
start this instance
=cut
sub start {
my ($self) = @_;
$self->pid($self->_pid_check($self->code->($self)));
print "# Start " . $self->id . " and run with pid: " . $self->pid . "\n" if $ENV{C_P_DEBUG};
return $self;
}
sub _pid_check {
my ($self, $pid) = @_;
if (!defined $pid) {
die 'Undefined PID';
}
if ($pid !~ /^(?:-)?\d+$/) {
die "Returned PID ($pid) " . $self->name . " isn't number!";
}
return $pid;
}
=head2 is_alive()
is this instance alive?
=cut
sub is_alive {
my ($self) = @_;
return defined $self->pid && !waitpid $self->pid, WNOHANG;
}
sub DESTROY {
my ($self) = @_;
# destroy only in parent (main) process
# ignore pseudo-process (<0) is threads and threads died with main
if (defined $self->parent_pid && $self->parent_pid == $$ && $self->pid && $self->pid > 0) {
print "# Kill PID ".$self->pid."\n" if $ENV{C_P_DEBUG};
kill 15, $self->pid;
}
}
=head1 LICENSE
Copyright (C) Avast Software.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 AUTHOR
Jan Seidl E<lt>seidl@avast.comE<gt>
=cut
1;