Skip to content

Commit

Permalink
allow Mojo::IOLoop to signal when it is shutting down gracefully
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Feb 17, 2015
1 parent 7cf093a commit b563152
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 8 deletions.
1 change: 1 addition & 0 deletions Changes
Expand Up @@ -8,6 +8,7 @@
- Removed accept_interval, lock_file and lock_timeout parameters from
Hypntoad.
- Added stop_gracefully method to Mojo::IOLoop.
- Added finish event to Mojo::IOLoop.
- Reduced idle CPU usage of Mojo::IOLoop and Mojo::Server::Prefork.
- Improved app generator command to use current best practices.
- Fixed bug in Mojo::IOLoop where connection limits were not properly
Expand Down
22 changes: 18 additions & 4 deletions lib/Mojo/IOLoop.pm
@@ -1,5 +1,5 @@
package Mojo::IOLoop;
use Mojo::Base -base;
use Mojo::Base 'Mojo::EventEmitter';

# "Professor: Amy, technology isn't intrinsically good or evil. It's how it's
# used. Like the death ray."
Expand Down Expand Up @@ -143,7 +143,7 @@ sub stop { _instance(shift)->reactor->stop }

sub stop_gracefully {
my $self = _instance(shift)->_not_accepting;
$self->{stop} ||= $self->recurring(1 => \&_stop);
$self->{stop} ||= $self->emit('finish')->recurring(1 => \&_stop);
}

sub stream {
Expand Down Expand Up @@ -311,6 +311,20 @@ C<MOJO_NO_TLS> environment variables.
See L<Mojolicious::Guides::Cookbook/"REAL-TIME WEB"> for more.
=head1 EVENTS
L<Mojo::IOLoop> inherits all events from L<Mojo::EventEmitter> and can emit
the following new ones.
=head2 finish
$loop->on(finish => sub {
my $loop = shift;
...
});
Emitted when the event loop shuts down gracefully.
=head1 ATTRIBUTES
L<Mojo::IOLoop> implements the following attributes.
Expand Down Expand Up @@ -366,8 +380,8 @@ L<Mojo::Reactor/"error">.
=head1 METHODS
L<Mojo::IOLoop> inherits all methods from L<Mojo::Base> and implements the
following new ones.
L<Mojo::IOLoop> inherits all methods from L<Mojo::EventEmitter> and implements
the following new ones.
=head2 acceptor
Expand Down
6 changes: 4 additions & 2 deletions lib/Mojo/Server/Prefork.pm
Expand Up @@ -154,8 +154,10 @@ sub _spawn {

# Heartbeat messages
weaken $self;
my $cb = sub { $self->_heartbeat(shift->max_connections ? 0 : 1) };
my $loop = $self->ioloop;
my $loop = $self->ioloop;
my $finished = 0;
$loop->on(finish => sub { $finished = 1 });
my $cb = sub { $self->_heartbeat($finished) };
$loop->next_tick($cb);
$loop->recurring($self->heartbeat_interval => $cb);

Expand Down
4 changes: 2 additions & 2 deletions lib/Mojolicious/Guides.pod
Expand Up @@ -227,6 +227,8 @@ This is the class hierarchy of the L<Mojolicious> distribution.

=back

=item * L<Mojo::IOLoop>

=item * L<Mojo::IOLoop::Client>

=item * L<Mojo::IOLoop::Delay>
Expand Down Expand Up @@ -301,8 +303,6 @@ This is the class hierarchy of the L<Mojolicious> distribution.

=item * L<Mojo::Home>

=item * L<Mojo::IOLoop>

=item * L<Mojo::JSON::Pointer>

=item * L<Mojo::Loader>
Expand Down
3 changes: 3 additions & 0 deletions t/mojo/ioloop.t
Expand Up @@ -260,12 +260,15 @@ is $client, 'works!', 'full message has been written';
# Graceful shutdown
$err = '';
$loop = Mojo::IOLoop->new;
my $finish;
$loop->on(finish => sub { $finish++ });
$loop->stop_gracefully;
$loop->remove(
$loop->client({port => Mojo::IOLoop::Server->generate_port} => sub { }));
$loop->timer(3 => sub { shift->stop; $err = 'failed' });
$loop->start;
ok !$err, 'no error';
is $finish, 1, 'finish event has been emitted once';

# Graceful shutdown (max_accepts)
$err = '';
Expand Down

0 comments on commit b563152

Please sign in to comment.