move all core use of "debug" to use "trace" instead (or almost all of them)
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Script / Server.pm
CommitLineData
0ba6e8aa 1package Catalyst::Script::Server;
a3ca4468 2use Moose;
b89d8b98 3use Catalyst::Utils;
e7399d8b 4use Class::Load qw(try_load_class load_class);
59804176 5use namespace::autoclean;
a3ca4468 6
d3082fac 7with 'Catalyst::ScriptRole';
a3ca4468 8
f59a9d1b 9has debug => (
4387c692 10 traits => [qw(Getopt)],
11 cmd_aliases => 'd',
8c848c33 12 isa => 'Bool',
4387c692 13 is => 'ro',
d3082fac 14 documentation => q{Force debug mode},
e46bf32c 15);
16
14d2fa6a 17has trace => (
18 traits => [qw(Getopt)],
19 cmd_aliases => 'd',
20 isa => 'Integer',
21 is => 'ro',
22 documentation => q{Force trace mode},
23);
24
57dc50b0 25has host => (
4387c692 26 traits => [qw(Getopt)],
27 cmd_aliases => 'h',
8c848c33 28 isa => 'Str',
4387c692 29 is => 'ro',
b1bfeea6 30 # N.B. undef (the default) means we bind on all interfaces on the host.
3bd410a9 31 documentation => 'Specify a hostname or IP on this host for the server to bind to',
41b55019 32);
90b481b1 33
57dc50b0 34has fork => (
4387c692 35 traits => [qw(Getopt)],
36 cmd_aliases => 'f',
8c848c33 37 isa => 'Bool',
4387c692 38 is => 'ro',
39 default => 0,
53c6ec79 40 documentation => 'Fork the server to be able to serve multiple requests at once',
90b481b1 41);
42
bc6fa9fc 43has port => (
4387c692 44 traits => [qw(Getopt)],
45 cmd_aliases => 'p',
8c848c33 46 isa => 'Int',
4387c692 47 is => 'ro',
b89d8b98 48 default => sub {
56eb9db4 49 Catalyst::Utils::env_value(shift->application_name, 'port') || 3000
b89d8b98 50 },
53c6ec79 51 documentation => 'Specify a different listening port (to the default port 3000)',
204c6935 52);
53
a6878cd8 54use Moose::Util::TypeConstraints;
55class_type 'MooseX::Daemonize::Pid::File';
fa38321d 56subtype 'Catalyst::Script::Server::Types::Pidfile',
51e2ff98 57 as 'MooseX::Daemonize::Pid::File';
58
8c848c33 59coerce 'Catalyst::Script::Server::Types::Pidfile', from 'Str', via {
e7399d8b 60 my ($success, $error) = try_load_class("MooseX::Daemonize::Pid::File");
61 warn("Could not load MooseX::Daemonize::Pid::File, needed for --pid option: $error\n"),
62 exit 1 if not $success;
a6878cd8 63 MooseX::Daemonize::Pid::File->new( file => $_ );
64};
65MooseX::Getopt::OptionTypeMap->add_option_type_to_map(
fa38321d 66 'Catalyst::Script::Server::Types::Pidfile' => '=s',
a6878cd8 67);
57dc50b0 68has pidfile => (
4387c692 69 traits => [qw(Getopt)],
70 cmd_aliases => 'pid',
fa38321d 71 isa => 'Catalyst::Script::Server::Types::Pidfile',
4387c692 72 is => 'ro',
d3082fac 73 documentation => 'Specify a pidfile',
a6878cd8 74 coerce => 1,
75 predicate => '_has_pidfile',
41b55019 76);
77
df894348 78# Override MooseX::Daemonize
79sub dont_close_all_files { 1 }
a6878cd8 80sub BUILD {
81 my $self = shift;
00064198 82
07b56dc9 83 if ($self->background) {
84 # FIXME - This is evil. Should we just add MX::Daemonize to the deps?
e7399d8b 85 my ($success, $error) = try_load_class("MooseX::Daemonize::Core");
86 warn("MooseX::Daemonize is needed for the --background option: $error\n"),
87 exit 1 if not $success;
0599f47b 88 ($success, $error) = try_load_class("POSIX");
e7399d8b 89 warn("$error\n"), exit 1 if not $success;
07b56dc9 90 MooseX::Daemonize::Core->meta->apply($self);
df894348 91 POSIX::close($_) foreach (0..2);
07b56dc9 92 }
a6878cd8 93}
94
57dc50b0 95has keepalive => (
4387c692 96 traits => [qw(Getopt)],
97 cmd_aliases => 'k',
8c848c33 98 isa => 'Bool',
4387c692 99 is => 'ro',
100 default => 0,
53c6ec79 101 documentation => 'Support keepalive',
bd31e11f 102);
103
57dc50b0 104has background => (
4387c692 105 traits => [qw(Getopt)],
106 cmd_aliases => 'bg',
8c848c33 107 isa => 'Bool',
4387c692 108 is => 'ro',
109 default => 0,
d3082fac 110 documentation => 'Run in the background',
57dc50b0 111);
4b3881d4 112
8f01ed5f 113has restart => (
4387c692 114 traits => [qw(Getopt)],
115 cmd_aliases => 'r',
8c848c33 116 isa => 'Bool',
4387c692 117 is => 'ro',
56eb9db4 118 default => sub {
119 Catalyst::Utils::env_value(shift->application_name, 'reload') || 0;
120 },
53c6ec79 121 documentation => 'use Catalyst::Restarter to detect code changes and restart the application',
57dc50b0 122);
a7dea640 123
124has restart_directory => (
4387c692 125 traits => [qw(Getopt)],
1c517146 126 cmd_aliases => [ 'rdir', 'restartdirectory' ],
8c848c33 127 isa => 'ArrayRef[Str]',
4387c692 128 is => 'ro',
d3082fac 129 documentation => 'Restarter directory to watch',
4387c692 130 predicate => '_has_restart_directory',
8f01ed5f 131);
132
57dc50b0 133has restart_delay => (
4387c692 134 traits => [qw(Getopt)],
135 cmd_aliases => 'rd',
8c848c33 136 isa => 'Int',
4387c692 137 is => 'ro',
d3082fac 138 documentation => 'Set a restart delay',
4387c692 139 predicate => '_has_restart_delay',
70871584 140);
141
880d1f8b 142{
143 use Moose::Util::TypeConstraints;
144
8c848c33 145 my $tc = subtype 'Catalyst::Script::Server::Types::RegexpRef', as 'RegexpRef';
146 coerce $tc, from 'Str', via { qr/$_/ };
880d1f8b 147
148 MooseX::Getopt::OptionTypeMap->add_option_type_to_map($tc => '=s');
149
150 has restart_regex => (
4387c692 151 traits => [qw(Getopt)],
152 cmd_aliases => 'rr',
153 isa => $tc,
154 coerce => 1,
155 is => 'ro',
880d1f8b 156 documentation => 'Restart regex',
4387c692 157 predicate => '_has_restart_regex',
880d1f8b 158 );
159}
ee7aabd6 160
57dc50b0 161has follow_symlinks => (
4387c692 162 traits => [qw(Getopt)],
163 cmd_aliases => 'sym',
8c848c33 164 isa => 'Bool',
4387c692 165 is => 'ro',
166 default => 0,
d3082fac 167 documentation => 'Follow symbolic links',
4387c692 168 predicate => '_has_follow_symlinks',
bbd42ac8 169);
a3ca4468 170
a6878cd8 171sub _plack_engine_name {
172 my $self = shift;
0cca6153 173 return $self->fork || $self->keepalive ? 'Starman' : 'Standalone';
a6878cd8 174}
175
3453b929 176sub _restarter_args {
177 my $self = shift;
34be7d45 178
10255473 179 return (
34be7d45 180 argv => $self->ARGV,
181 start_sub => sub { $self->_run_application },
182 ($self->_has_follow_symlinks ? (follow_symlinks => $self->follow_symlinks) : ()),
183 ($self->_has_restart_delay ? (sleep_interval => $self->restart_delay) : ()),
184 ($self->_has_restart_directory ? (directories => $self->restart_directory) : ()),
880d1f8b 185 ($self->_has_restart_regex ? (filter => $self->restart_regex) : ()),
a024e9ad 186 ),
187 (
8dde82d5 188 map { $_ => $self->$_ } qw(application_name host port debug pidfile fork background keepalive)
34be7d45 189 );
3453b929 190}
191
75fe0bb3 192has restarter_class => (
193 is => 'ro',
8c848c33 194 isa => 'Str',
75fe0bb3 195 lazy => 1,
196 default => sub {
197 my $self = shift;
198 Catalyst::Utils::env_value($self->application_name, 'RESTARTER') || 'Catalyst::Restarter';
199 }
200);
201
a3ca4468 202sub run {
3453b929 203 my $self = shift;
57dc50b0 204
53c6ec79 205 local $ENV{CATALYST_DEBUG} = 1
206 if $self->debug;
abee32cb 207
14d2fa6a 208 local $ENV{CATALYST_TRACE} = $self->trace
209 if $self->trace;
210
a7dea640 211 if ( $self->restart ) {
212 die "Cannot run in the background and also watch for changed files.\n"
213 if $self->background;
00064198 214 die "Cannot write out a pid file and fork for the restarter.\n"
215 if $self->_has_pidfile;
a7dea640 216
53c6ec79 217 # If we load this here, then in the case of a restarter, it does not
218 # need to be reloaded for each restart.
219 require Catalyst;
220
221 # If this isn't done, then the Catalyst::Devel tests for the restarter
222 # fail.
223 $| = 1 if $ENV{HARNESS_ACTIVE};
224
a024e9ad 225 Catalyst::Utils::ensure_class_loaded($self->restarter_class);
a7dea640 226
75fe0bb3 227 my $subclass = $self->restarter_class->pick_subclass;
a7dea640 228
a7dea640 229 my $restarter = $subclass->new(
3453b929 230 $self->_restarter_args()
a7dea640 231 );
232
233 $restarter->run_and_watch;
234 }
235 else {
07b56dc9 236 if ($self->background) {
237 $self->daemon_fork;
238
239 return 1 unless $self->is_daemon;
240
e7399d8b 241 load_class($self->application_name);
07b56dc9 242
243 $self->daemon_detach;
244 }
245
00064198 246 $self->pidfile->write
247 if $self->_has_pidfile;
248
d3082fac 249 $self->_run_application;
a7dea640 250 }
251
252
57dc50b0 253}
254
36a53c3a 255sub _plack_loader_args {
256 my ($self) = shift;
257 return (
258 port => $self->port,
259 host => $self->host,
260 keepalive => $self->keepalive ? 100 : 1,
54ab9446 261 server_ready => sub {
262 my ($args) = @_;
263
264 my $name = $args->{server_software} || ref($args); # $args is $server
265 my $host = $args->{host} || 0;
266 my $proto = $args->{proto} || 'http';
267
268 print STDERR "$name: Accepting connections at $proto://$host:$args->{port}/\n";
269 },
36a53c3a 270 );
271}
272
aee7cdcc 273around _application_args => sub {
274 my ($orig, $self) = @_;
d3082fac 275 return (
bc6fa9fc 276 $self->port,
d3082fac 277 $self->host,
57dc50b0 278 {
aee7cdcc 279 %{ $self->$orig },
d3082fac 280 map { $_ => $self->$_ } qw/
281 fork
282 keepalive
283 background
284 pidfile
285 keepalive
286 follow_symlinks
aee7cdcc 287 port
288 host
d3082fac 289 /,
290 },
a3ca4468 291 );
aee7cdcc 292};
5b923b0b 293
2e81e132 294__PACKAGE__->meta->make_immutable;
0ba6e8aa 2951;
e46bf32c 296
297=head1 NAME
298
cbaaecc0 299Catalyst::Script::Server - Catalyst test server
e46bf32c 300
301=head1 SYNOPSIS
302
cbaaecc0 303 myapp_server.pl [options]
e46bf32c 304
305 Options:
4b3881d4 306 -d --debug force debug mode
307 -f --fork handle each request in a new process
e46bf32c 308 (defaults to false)
3dcfb4c8 309 --help display this help and exits
310 -h --host host (defaults to all)
4b3881d4 311 -p --port port (defaults to 3000)
312 -k --keepalive enable keep-alive connections
313 -r --restart restart when files get modified
314 (defaults to false)
87f5a448 315 --rd --restart_delay delay between file checks
e46bf32c 316 (ignored if you have Linux::Inotify2 installed)
87f5a448 317 --rr --restart_regex regex match files that trigger
e46bf32c 318 a restart when modified
319 (defaults to '\.yml$|\.yaml$|\.conf|\.pm$')
87f5a448 320 --rdir --restart_directory the directory to search for
6ab9f4af 321 modified files, can be set multiple times
e46bf32c 322 (defaults to '[SCRIPT_DIR]/..')
4b3881d4 323 --sym --follow_symlinks follow symlinks in search directories
e46bf32c 324 (defaults to false. this is a no-op on Win32)
4b3881d4 325 --bg --background run the process in the background
326 --pid --pidfile specify filename for pid file
e46bf32c 327
328 See also:
329 perldoc Catalyst::Manual
330 perldoc Catalyst::Manual::Intro
331
332=head1 DESCRIPTION
333
cbaaecc0 334Run a Catalyst test server for this application.
e46bf32c 335
383c5be6 336=head1 SEE ALSO
337
338L<Catalyst::ScriptRunner>
339
e46bf32c 340=head1 AUTHORS
341
342Catalyst Contributors, see Catalyst.pm
343
344=head1 COPYRIGHT
345
346This library is free software. You can redistribute it and/or modify
347it under the same terms as Perl itself.
348
349=cut