File Coverage

blib/lib/Ubic/Service/Hypnotoad.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package Ubic::Service::Hypnotoad;
2             # ABSTRACT: Ubic service module for Mojolicious Hypnotoad
3             $Ubic::Service::Hypnotoad::VERSION = '0.2001';
4 1     1   31239 use strict;
  1         2  
  1         38  
5 1     1   4 use warnings;
  1         1  
  1         28  
6              
7 1     1   3698 use parent qw(Ubic::Service::Skeleton);
  1         1164  
  1         7  
8              
9             use Ubic::Result qw(result);
10             use File::Basename;
11             use Time::HiRes qw(time);
12             use Capture::Tiny qw(:all);
13              
14              
15              
16              
17             sub new {
18             my ($class, $opt) = @_;
19              
20             my $bin = [split /\s+/, ($opt->{'bin'} // 'hypnotoad')] unless ref $opt->{bin} eq 'ARRAY';
21             @$bin or die "missing 'bin' parameter in new";
22             my $app = $opt->{'app'} // '';
23             length $app or die "missing 'app' parameter in new";
24             my $pid_file = $opt->{'pid_file'} // dirname($app).'/hypnotoad.pid';
25             length $pid_file or die "missing 'pid_file' parameter in new";
26              
27             my %env = %{ $opt->{'env'} // {} };
28              
29             return bless {
30             bin => $bin,
31             app => $app,
32             env => \%env,
33             pid_file => $pid_file,
34             start_time => undef,
35             stop_time => undef,
36             cwd => $opt->{cwd},
37             }, $class;
38             }
39              
40             sub _read_pid {
41             my $self = shift;
42              
43             return eval {
44             open my $fh, $self->{'pid_file'} or die;
45             my $pid = (scalar(<$fh>) =~ /(\d+)/g)[0];
46             close $fh;
47             $pid;
48             };
49             }
50              
51             sub status_impl {
52             my $self = shift;
53              
54             my $pid = $self->_read_pid;
55              
56             if ($self->{'start_time'} and $self->{'start_time'} + 5 > time) {
57             return result('broken') if ! $pid;
58             }
59             $self->{'start_time'} = undef;
60              
61             if (! $pid) {
62             $self->{'stop_time'} = undef;
63             return result('not running');
64             }
65              
66             if ($self->{'stop_time'} and $self->{'stop_time'} + 5 > time) {
67             return result('broken');
68             }
69              
70             my ($i, $running, $old_pid) = (0);
71             do {
72             $i++;
73             $old_pid = $pid;
74             $running = kill 0, $old_pid;
75             $pid = $self->_read_pid or return result('not running');
76             } until ($pid == $old_pid or $i > 5);
77              
78             $pid == $old_pid or return result('broken');
79              
80             return $running ? result('running', 'pid '.$pid) : result('not running');
81             }
82              
83             sub start_impl {
84             my $self = shift;
85              
86             local %ENV = (%ENV, %{ $self->{'env'} });
87              
88             if (defined $self->{cwd}) {
89             chdir $self->{cwd} or die "chdir to '$self->{cwd}' failed: $!";
90             }
91              
92             system(@{$self->{'bin'}}, $self->{'app'});
93             $self->{'start_time'} = time;
94             $self->{'stop_time'} = undef;
95              
96             return result('starting');
97             }
98              
99             sub stop_impl {
100             my $self = shift;
101              
102             if (defined $self->{cwd}) {
103             chdir $self->{cwd} or die "chdir to '$self->{cwd}' failed: $!";
104             }
105              
106             local %ENV = (%ENV, %{ $self->{'env'} });
107             my (undef, $stderr) = capture {
108             system(@{$self->{'bin'}}, '-s', $self->{'app'});
109             };
110             print $stderr if length $stderr;
111             $self->{'stop_time'} = time;
112             $self->{'start_time'} = undef;
113              
114             return result('stopping');
115             }
116              
117             sub reload {
118             my $self = shift;
119              
120             my $pid = $self->_read_pid or return 'not running';
121             my $ret = kill "USR2", $pid;
122             return $ret ? 'reloaded' : 'not running';
123             }
124              
125             sub timeout_options {
126             return {
127             start => {
128             step => 0.1,
129             trials => 10,
130             },
131             stop => {
132             step => 0.1,
133             trials => 10,
134             },
135             };
136             }
137              
138              
139              
140              
141              
142             1;
143              
144             __END__