package Zing::Logic::Watcher; use 5.014; use strict; use warnings; use registry 'Zing::Types'; use routines; use Data::Object::Class; use Data::Object::ClassHas; extends 'Zing::Logic'; use Zing::Flow; use Zing::Fork; our $VERSION = '0.22'; # VERSION # ATTRIBUTES has 'fork' => ( is => 'ro', isa => 'Fork', new => 1 ); fun new_fork($self) { Zing::Fork->new(parent => $self->process, scheme => $self->scheme) } has 'on_launch' => ( is => 'ro', isa => 'CodeRef', new => 1, ); fun new_on_launch($self) { $self->can('handle_launch_event') } has 'on_monitor' => ( is => 'ro', isa => 'CodeRef', new => 1, ); fun new_on_monitor($self) { $self->can('handle_monitor_event') } has 'on_sanitize' => ( is => 'ro', isa => 'CodeRef', new => 1, ); fun new_on_sanitize($self) { $self->can('handle_sanitize_event') } has 'scheme' => ( is => 'ro', isa => 'Scheme', new => 1 ); fun new_scheme($self) { $self->process->scheme } has 'size' => ( is => 'ro', isa => 'Int', new => 1 ); fun new_size($self) { $self->scheme->[2] } # METHODS method flow() { my $step_0 = $self->next::method; my $step_1 = Zing::Flow->new( name => 'on_launch', code => fun($step, $loop) { $self->trace('on_launch')->($self) } ); my $step_2 = $step_1->next(Zing::Flow->new( name => 'on_monitor', code => fun($step, $loop) { $self->trace('on_monitor')->($self) } )); my $step_3 = $step_2->next(Zing::Flow->new( name => 'on_sanitize', code => fun($step, $loop) { $self->trace('on_sanitize')->($self) } )); $step_0->append($step_1); $step_0 } method handle_launch_event() { my $fork = $self->fork; my $process = $self->process; if ($self->interupt) { return 0; } if ($process->loop->last) { return 0; } if ($process->loop->stop) { return 0; } my $max_forks = $self->size; my $has_forks = keys %{$fork->processes}; if ($has_forks > $max_forks) { return 0; # wtf } if (my $needs = $max_forks - $has_forks) { for (1..$needs) { $fork->execute; } } else { return 0; } } method handle_monitor_event() { my $fork = $self->fork; return $fork->monitor; } method handle_sanitize_event() { my $fork = $self->fork; return $fork->sanitize; } method signals() { my $trapped = {}; my $fork = $self->fork; $trapped->{INT} = sub { $self->trace('interupt', 'INT'); $fork->terminate($self->interupt); do {0} while ($fork->sanitize); # reap children $self->process->winddown; }; $trapped->{QUIT} = sub { $self->trace('interupt', 'QUIT'); $fork->terminate($self->interupt); do {0} while ($fork->sanitize); # reap children $self->process->winddown; }; $trapped->{TERM} = sub { $self->trace('interupt', 'TERM'); $fork->terminate($self->interupt); do {0} while ($fork->sanitize); # reap children $self->process->winddown; }; $trapped->{USR1} = sub { $self->note('handles "interupt", with, USR1'); $fork->terminate('INT'); do {0} while ($fork->sanitize); # reap children }; $trapped->{USR2} = sub { $self->note('handles "interupt", with, USR2'); $fork->terminate('INT'); do {0} while ($fork->sanitize); # reap children }; return $trapped; } 1; =encoding utf8 =head1 NAME Zing::Logic::Watcher - Watcher Logic =cut =head1 ABSTRACT Watcher Process Logic Chain =cut =head1 SYNOPSIS package Process; use parent 'Zing::Process'; sub scheme { ['MyApp', [], 1] } package main; use Zing::Logic::Watcher; my $logic = Zing::Logic::Watcher->new(process => Process->new); # $logic->execute; =cut =head1 DESCRIPTION This package provides the logic (or logic chain) to be executed by the watcher process event-loop. =cut =head1 INHERITS This package inherits behaviors from: L =cut =head1 LIBRARIES This package uses type constraints from: L =cut =head1 ATTRIBUTES This package has the following attributes: =cut =head2 fork fork(Fork) This attribute is read-only, accepts C<(Fork)> values, and is optional. =cut =head2 interupt interupt(Interupt) This attribute is read-only, accepts C<(Interupt)> values, and is optional. =cut =head2 on_launch on_launch(CodeRef) This attribute is read-only, accepts C<(CodeRef)> values, and is optional. =cut =head2 on_monitor on_monitor(CodeRef) This attribute is read-only, accepts C<(CodeRef)> values, and is optional. =cut =head2 on_perform on_perform(CodeRef) This attribute is read-only, accepts C<(CodeRef)> values, and is optional. =cut =head2 on_receive on_receive(CodeRef) This attribute is read-only, accepts C<(CodeRef)> values, and is optional. =cut =head2 on_register on_register(CodeRef) This attribute is read-only, accepts C<(CodeRef)> values, and is optional. =cut =head2 on_reset on_reset(CodeRef) This attribute is read-only, accepts C<(CodeRef)> values, and is optional. =cut =head2 on_sanitize on_sanitize(CodeRef) This attribute is read-only, accepts C<(CodeRef)> values, and is optional. =cut =head2 on_suicide on_suicide(CodeRef) This attribute is read-only, accepts C<(CodeRef)> values, and is optional. =cut =head2 process process(Process) This attribute is read-only, accepts C<(Process)> values, and is required. =cut =head2 scheme scheme(Scheme) This attribute is read-only, accepts C<(Scheme)> values, and is optional. =cut =head2 size size(Int) This attribute is read-only, accepts C<(Int)> values, and is optional. =cut =head1 METHODS This package implements the following methods: =cut =head2 flow flow() : Flow The flow method builds and returns the logic flow for the process event-loop. =over 4 =item flow example #1 # given: synopsis my $flow = $logic->flow; =back =cut =head2 signals signals() : HashRef The signals method builds and returns the process signal handlers. =over 4 =item signals example #1 # given: synopsis my $signals = $logic->signals; =back =cut =head1 AUTHOR Al Newkirk, C =head1 LICENSE Copyright (C) 2011-2019, Al Newkirk, et al. This is free software; you can redistribute it and/or modify it under the terms of the The Apache License, Version 2.0, as elucidated in the L<"license file"|https://github.com/iamalnewkirk/zing/blob/master/LICENSE>. =head1 PROJECT L L L L L L =cut