File Coverage

blib/lib/HealthCheck/Parallel.pm
Criterion Covered Total %
statement 54 54 100.0
branch 23 24 95.8
condition 12 19 63.1
subroutine 12 12 100.0
pod 1 1 100.0
total 102 110 92.7


line stmt bran cond sub pod time code
1             package HealthCheck::Parallel;
2              
3 6     6   1408974 use v5.10;
  6         54  
4 6     6   36 use strict;
  6         12  
  6         126  
5 6     6   30 use warnings;
  6         12  
  6         240  
6              
7 6     6   2544 use parent 'HealthCheck';
  6         1818  
  6         36  
8              
9 6     6   54012 use Carp;
  6         78  
  6         324  
10 6     6   3582 use Parallel::ForkManager;
  6         456840  
  6         246  
11              
12             # ABSTRACT: A HealthCheck that uses parallelization for running checks
13 6     6   60 use version;
  6         12  
  6         54  
14             our $VERSION = 'v0.0.2'; # VERSION
15              
16             sub new {
17 17     17 1 72714 my ( $class, %params ) = @_;
18              
19 17   100     232 $params{max_procs} //= 4;
20              
21 17         132 my $self = $class->SUPER::new( %params );
22              
23 17         1492 $self->_validate_max_procs( $params{max_procs} );
24 16         119 $self->_validate_child_init( $params{child_init} );
25              
26 15         75 return $self;
27             }
28              
29             sub _run_checks {
30 19     19   28789 my ( $self, $checks, $params ) = @_;
31              
32             $self->_validate_max_procs( $params->{max_procs} )
33 19 100       146 if exists $params->{max_procs};
34              
35             $self->_validate_child_init( $params->{child_init} )
36 18 100       80 if exists $params->{child_init};
37              
38 17   66     136 my $max_procs = $params->{max_procs} // $self->{max_procs};
39 17   66     207 my $child_init = $params->{child_init} // $self->{child_init};
40 17   33     168 my $tempdir = $params->{tempdir} // $self->{tempdir};
41              
42 17         46 my @results;
43             my $forker;
44              
45 17 100       59 if ( $max_procs > 1 ) {
46 13 50       304 $forker = Parallel::ForkManager->new(
47             $max_procs,
48             $tempdir ? $tempdir : (),
49             );
50              
51             $forker->run_on_finish(sub {
52 13     13   8017961 my ( $pid, $exit_code, $ident, $exit_sig, $core_dump, $ret ) = @_;
53              
54             # Child process had some error.
55 13 100       135 if ( $exit_code != 0 ) {
56 4         172 $results[ $ident ] = {
57             status => 'CRITICAL',
58             info => "Child process exited with code $exit_code.",
59             };
60             }
61             else {
62             # Keep results in the same order that they were provided.
63 9         52 $results[ $ident ] = $ret->[0];
64             }
65 13         33765 });
66             }
67              
68 17         168 my $i = 0;
69 17         53 for my $check ( @$checks ) {
70 28 100       10093 if ( $forker ) {
71 20 100       229 $forker->start( $i++ ) and next;
72 5 100       17031 $child_init->() if $child_init;
73             }
74              
75 12         418 my @r = $self->_run_check( $check, $params );
76              
77 11 100 0     1810 $forker->finish( 0, \@r ) and next
78             if $forker;
79              
80             # Non-forked process.
81 8         84 push @results, @r;
82             }
83              
84 12 100       9805 $forker->wait_all_children if $forker;
85              
86 12         1053 return @results;
87             }
88              
89             sub _validate_max_procs {
90 22     22   58 my ( $self, $max_procs ) = @_;
91              
92 22 100 66     876 croak "max_procs must be a zero or positive integer!"
93             unless $max_procs =~ /^\d+$/ && $max_procs >= 0;
94             }
95              
96             sub _validate_child_init {
97 17     17   62 my ( $self, $child_init ) = @_;
98              
99 17 100 100     452 croak "child_init must be a code reference!"
100             if defined $child_init && ref( $child_init ) ne 'CODE';
101             }
102              
103             1;
104              
105             __END__