File Coverage

blib/lib/Mojo/Server/Morbo.pm
Criterion Covered Total %
statement 12 43 27.9
branch 0 22 0.0
condition 0 6 0.0
subroutine 4 9 44.4
pod 1 1 100.0
total 17 81 20.9


line stmt bran cond sub pod time code
1             package Mojo::Server::Morbo;
2 1     1   521 use Mojo::Base -base;
  1         5  
  1         7  
3              
4             # "Linda: With Haley's Comet out of ice, Earth is experiencing the devastating
5             # effects of sudden, intense global warming.
6             # Morbo: Morbo is pleased but sticky."
7 1     1   8 use Mojo::Loader qw(load_class);
  1         2  
  1         48  
8 1     1   6 use Mojo::Server::Daemon;
  1         3  
  1         6  
9 1     1   7 use POSIX qw(WNOHANG);
  1         2  
  1         9  
10              
11             has backend => sub {
12             my $backend = $ENV{MOJO_MORBO_BACKEND} || 'Poll';
13             $backend = "Mojo::Server::Morbo::Backend::$backend";
14             return $backend->new unless my $e = load_class $backend;
15             die $e if ref $e;
16             die qq{Can't find Morbo backend class "$backend" in \@INC. (@INC)\n};
17             };
18             has daemon => sub { Mojo::Server::Daemon->new };
19             has silent => 1;
20              
21             sub run {
22 0     0 1   my ($self, $app) = @_;
23              
24             # Clean manager environment
25             local $SIG{INT} = local $SIG{TERM} = sub {
26 0     0     $self->{finished} = 1;
27 0 0         kill 'TERM', $self->{worker} if $self->{worker};
28 0           };
29 0           unshift @{$self->backend->watch}, $0 = $app;
  0            
30 0           $self->{modified} = 1;
31              
32             # Prepare and cache listen sockets for smooth restarting
33 0           $self->daemon->start->stop;
34              
35 0   0       $self->_manage until $self->{finished} && !$self->{worker};
36 0           exit 0;
37             }
38              
39             sub _manage {
40 0     0     my $self = shift;
41              
42 0 0         if (my @files = @{$self->backend->modified_files}) {
  0            
43 0 0         say @files == 1
    0          
44 0           ? qq{File "@{[$files[0]]}" changed, restarting.}
45 0           : qq{@{[scalar @files]} files changed, restarting.}
46             unless $self->silent;
47 0 0         kill 'TERM', $self->{worker} if $self->{worker};
48 0           $self->{modified} = 1;
49             }
50              
51 0 0         if (my $pid = $self->{worker}) {
52 0 0         delete $self->{worker} if waitpid($pid, WNOHANG) == $pid;
53             }
54              
55 0 0 0       $self->_spawn if !$self->{worker} && delete $self->{modified};
56             }
57              
58             sub _spawn {
59 0     0     my $self = shift;
60              
61             # Manager
62 0           my $manager = $$;
63 0 0         die "Can't fork: $!" unless defined(my $pid = $self->{worker} = fork);
64 0 0         return if $pid;
65              
66             # Worker
67 0           my $daemon = $self->daemon;
68 0           $daemon->load_app($self->backend->watch->[0])->server($daemon);
69 0 0   0     $daemon->ioloop->recurring(1 => sub { shift->stop unless kill 0, $manager });
  0            
70 0           $daemon->run;
71 0           exit 0;
72             }
73              
74             1;
75              
76             =encoding utf8
77              
78             =head1 NAME
79              
80             Mojo::Server::Morbo - Tonight at 11...DOOOOOOOOOOOOOOOM!
81              
82             =head1 SYNOPSIS
83              
84             use Mojo::Server::Morbo;
85              
86             my $morbo = Mojo::Server::Morbo->new;
87             $morbo->run('/home/sri/myapp.pl');
88              
89             =head1 DESCRIPTION
90              
91             L is a full featured, self-restart capable non-blocking I/O HTTP and WebSocket server, built
92             around the very well tested and reliable L, with IPv6, TLS, SNI, UNIX domain socket, Comet (long
93             polling), keep-alive and multiple event loop support. Note that the server uses signals for process management, so you
94             should avoid modifying signal handlers in your applications.
95              
96             To start applications with it you can use the L script.
97              
98             $ morbo ./myapp.pl
99             Web application available at http://127.0.0.1:3000
100              
101             For better scalability (epoll, kqueue) and to provide non-blocking name resolution, SOCKS5 as well as TLS support, the
102             optional modules L (4.32+), L (0.15+), L (0.64+) and L
103             (2.009+) will be used automatically if possible. Individual features can also be disabled with the C,
104             C and C environment variables.
105              
106             See L for more.
107              
108             =head1 SIGNALS
109              
110             The L process can be controlled at runtime with the following signals.
111              
112             =head2 INT, TERM
113              
114             Shut down server immediately.
115              
116             =head1 ATTRIBUTES
117              
118             L implements the following attributes.
119              
120             =head2 backend
121              
122             my $backend = $morbo->backend;
123             $morbo = $morbo->backend(Mojo::Server::Morbo::Backend::Poll->new);
124              
125             Backend, usually a L object.
126              
127             =head2 daemon
128              
129             my $daemon = $morbo->daemon;
130             $morbo = $morbo->daemon(Mojo::Server::Daemon->new);
131              
132             L object this server manages.
133              
134             =head2 silent
135              
136             my $bool = $morbo->silent;
137             $morbo = $morbo->silent($bool);
138              
139             Disable console messages, defaults to a true value.
140              
141             =head1 METHODS
142              
143             L inherits all methods from L and implements the following new ones.
144              
145             =head2 run
146              
147             $morbo->run('script/my_app');
148              
149             Run server for application and wait for L.
150              
151             =head1 SEE ALSO
152              
153             L, L, L.
154              
155             =cut