-
-
Save anonymous/e4d53f59cdb73a8b8d1d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/Mojo/Server/Hypnotoad.pm b/lib/Mojo/Server/Hypnotoad.pm | |
index d8e1682..9f08f29 100644 | |
--- a/lib/Mojo/Server/Hypnotoad.pm | |
+++ b/lib/Mojo/Server/Hypnotoad.pm | |
@@ -94,8 +94,11 @@ sub _manage { | |
my $self = shift; | |
# Upgraded | |
- my $log = $self->prefork->app->log; | |
+ my $prefork = $self->prefork; | |
+ my $log = $prefork->app->log; | |
if ($ENV{HYPNOTOAD_PID} && $ENV{HYPNOTOAD_PID} ne $$) { | |
+ my $workers = $prefork->workers; | |
+ return unless $workers && $prefork->healthy == $workers; | |
$log->info("Upgrade successful, stopping $ENV{HYPNOTOAD_PID}."); | |
kill 'QUIT', $ENV{HYPNOTOAD_PID}; | |
} | |
diff --git a/lib/Mojo/Server/Prefork.pm b/lib/Mojo/Server/Prefork.pm | |
index 1052111..f294ee6 100644 | |
--- a/lib/Mojo/Server/Prefork.pm | |
+++ b/lib/Mojo/Server/Prefork.pm | |
@@ -58,6 +58,10 @@ sub ensure_pid_file { | |
print $handle $$; | |
} | |
+sub healthy { | |
+ scalar grep { $_->{healthy} } values %{$_[0]->{pool}}; | |
+} | |
+ | |
sub run { | |
my $self = shift; | |
@@ -78,8 +82,9 @@ sub run { | |
local $SIG{INT} = local $SIG{TERM} = sub { $self->_term }; | |
local $SIG{CHLD} = sub { | |
while ((my $pid = waitpid -1, WNOHANG) > 0) { | |
- $self->app->log->debug("Worker $pid stopped.") | |
- if delete $self->emit(reap => $pid)->{pool}{$pid}; | |
+ next unless my $w = delete $self->emit(reap => $pid)->{pool}{$pid}; | |
+ $self->app->log->debug("Worker $pid stopped."); | |
+ $self->{finished}++ unless $w->{healthy}; | |
} | |
}; | |
local $SIG{QUIT} = sub { $self->_term(1) }; | |
@@ -96,7 +101,9 @@ sub run { | |
$self->_manage while $self->{running}; | |
} | |
-sub _heartbeat { | |
+sub _heartbeat { shift->{writer}->syswrite("$$:$_[0]\n") or exit 0 } | |
+ | |
+sub _heartbeats { | |
my $self = shift; | |
# Poll for heartbeats | |
@@ -109,7 +116,7 @@ sub _heartbeat { | |
my $time = steady_time; | |
while ($chunk =~ /(\d+):(\d)\n/g) { | |
next unless my $w = $self->{pool}{$1}; | |
- $self->emit(heartbeat => $1) and $w->{time} = $time; | |
+ @$w{qw(healthy time)} = (1, $time) and $self->emit(heartbeat => $1); | |
$w->{graceful} ||= $time if $2; | |
} | |
} | |
@@ -127,7 +134,7 @@ sub _manage { | |
elsif (!keys %{$self->{pool}}) { return delete $self->{running} } | |
# Wait for heartbeats | |
- $self->emit('wait')->_heartbeat; | |
+ $self->emit('wait')->_heartbeats; | |
my $interval = $self->heartbeat_interval; | |
my $ht = $self->heartbeat_timeout; | |
@@ -196,12 +203,9 @@ sub _spawn { | |
$loop->unlock(sub { flock $handle, LOCK_UN }); | |
# Heartbeat messages | |
- $loop->recurring( | |
- $self->heartbeat_interval => sub { | |
- my $graceful = shift->max_connections ? 0 : 1; | |
- $self->{writer}->syswrite("$$:$graceful\n") or exit 0; | |
- } | |
- ); | |
+ $loop->next_tick(sub { $self->_heartbeat(0) }); | |
+ my $cb = sub { $self->_heartbeat(shift->max_connections ? 0 : 1) }; | |
+ $loop->recurring($self->heartbeat_interval => $cb); | |
# Clean worker environment | |
$SIG{$_} = 'DEFAULT' for qw(INT TERM CHLD TTIN TTOU); | |
@@ -497,6 +501,12 @@ is not running. | |
Ensure L</"pid_file"> exists. | |
+=head2 healthy | |
+ | |
+ my $healthy = $prefork->healthy; | |
+ | |
+Number of active worker processes with a heartbeat. | |
+ | |
=head2 run | |
$prefork->run; | |
diff --git a/t/mojo/prefork.t b/t/mojo/prefork.t | |
index 2413f8d..d5e9290 100644 | |
--- a/t/mojo/prefork.t | |
+++ b/t/mojo/prefork.t | |
@@ -41,13 +41,14 @@ $prefork->on( | |
} | |
); | |
is $prefork->workers, 4, 'start with four workers'; | |
-my (@spawn, @reap, $worker, $tx, $graceful); | |
+my (@spawn, @reap, $worker, $tx, $graceful, $healthy); | |
$prefork->on(spawn => sub { push @spawn, pop }); | |
$prefork->once( | |
heartbeat => sub { | |
my ($prefork, $pid) = @_; | |
- $worker = $pid; | |
- $tx = Mojo::UserAgent->new->get("http://127.0.0.1:$port"); | |
+ $worker = $pid; | |
+ $healthy = $prefork->healthy; | |
+ $tx = Mojo::UserAgent->new->get("http://127.0.0.1:$port"); | |
kill 'QUIT', $$; | |
} | |
); | |
@@ -55,7 +56,9 @@ $prefork->on(reap => sub { push @reap, pop }); | |
$prefork->on(finish => sub { $graceful = pop }); | |
my $log = ''; | |
my $cb = $prefork->app->log->on(message => sub { $log .= pop }); | |
+is $prefork->healthy, 0, 'no healthy workers'; | |
$prefork->run; | |
+ok $healthy >= 1, 'healthy workers'; | |
is scalar @spawn, 4, 'four workers spawned'; | |
is scalar @reap, 4, 'four workers reaped'; | |
ok !!grep { $worker eq $_ } @spawn, 'worker has a heartbeat'; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment