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