1package Toadfarm::Command::start; 2use Mojo::Base 'Toadfarm::Command::tail'; 3 4use File::Basename 'dirname'; 5use File::Spec; 6use Time::HiRes 'usleep'; 7 8$ENV{TOADFARM_VERBOSE} //= $ENV{HARNESS_IS_VERBOSE} || -t STDOUT; 9 10has description => 'Toadfarm: Start the server if not already running'; 11 12sub run { shift->_start(@_) } 13 14sub _hypnotoad { 15 my $self = shift; 16 17 for my $p (File::Spec->path, dirname($^X)) { 18 my $exe = File::Spec->catfile($p, 'hypnotoad'); 19 return $exe if -r $exe; 20 } 21 22 die "Cannot find 'hypnotoad' in \$PATH."; 23} 24 25sub _is_running { 26 my $self = shift; 27 my $pid = $self->_pid; 28 return $pid && kill 0, $pid; 29} 30 31sub _end { 32 my ($self, $exit, $message) = @_; 33 34 if ($message and $ENV{TOADFARM_VERBOSE}) { 35 $self->_printf(" ...%s (%s)\n", $exit ? "fail!" : "done.", $message); 36 } 37 else { 38 $self->_printf(" ...%s\n", $exit ? "fail!" : "done."); 39 } 40 41 return $exit if $ENV{TOADFARM_NO_EXIT}; 42 exit $exit; 43} 44 45sub _log_daemon_msg { 46 my ($self, $message) = @_; 47 $self->_printf(" * $message\n", $self->app->moniker); 48} 49 50sub _pid { 51 my $self = shift; 52 my $file = $self->_pid_file; 53 return 0 unless $file and -e $file; 54 open my $PID, '<', $file or die "Unable to read pid_file $file: $!\n"; 55 my $pid = join '', <$PID>; 56 return $pid =~ /(\d+)/ ? $1 : 0; 57} 58 59sub _pid_file { 60 my $self = shift; 61 my $moniker = $self->app->moniker; 62 return $self->app->config->{hypnotoad}{pid_file} 63 || die "$moniker has invalid config: /hypnotoad/pid_file is not set.\n"; 64} 65 66sub _printf { shift; printf shift, @_; } 67 68sub _start { 69 my ($self, @args) = @_; 70 my $pid = $self->_pid; 71 my $tail = grep {/^--tail/} @args; 72 73 $self->_log_daemon_msg('Starting the process %s'); 74 75 # running 76 if ($self->_is_running) { 77 return $self->_tail(grep { !/^--tail/ } @args) if $tail; 78 return $self->_end(0, "already running with pid=$pid"); 79 } 80 81 # start 82 system $self->_hypnotoad, $0; 83 my $exit = $? >> 8; 84 return $self->_end($exit, "hypnotoad $0 = $exit") if $exit; 85 86 # wait until started 87 $self->_wait_for(5 => sub { shift->_is_running }); 88 89 # check if started 90 return $self->_end(3, 'daemon is not running') unless $self->_is_running; 91 return $self->_tail(grep { !/^--tail/ } @args) if $tail; 92 return $self->_end(0); 93 94} 95 96sub _wait_for { 97 my ($self, $cb) = (shift, pop); 98 my $timeout = shift || ($self->app->config->{hypnotoad}{graceful_timeout} || 20) + 5; 99 100 while ($timeout--) { 101 last if $self->$cb; 102 } 103 continue { 104 usleep(300e3); 105 } 106} 107 1081; 109 110=encoding utf8 111 112=head1 NAME 113 114Toadfarm::Command::start - Start a Toadfarm DSL script 115 116=head1 DESCRIPTION 117 118L<Toadfarm::Command::start> is a command for starting a L<Toadfarm> application. 119 120=head1 SYNOPSIS 121 122 $ /path/to/script.pl start 123 $ /path/to/script.pl start --tail <args> 124 125=head1 ATTRIBUTES 126 127=head2 description 128 129Short description of command, used for the command list. 130 131=head1 METHODS 132 133=head2 run 134 135Run command. 136 137=head1 COPYRIGHT AND LICENSE 138 139Copyright (C) 2014, Jan Henning Thorsen 140 141This program is free software, you can redistribute it and/or modify it under 142the terms of the Artistic License version 2.0. 143 144=head1 AUTHOR 145 146Jan Henning Thorsen - C<jhthorsen@cpan.org> 147 148=cut 149