Patch to make restarter class configurable / settable in prefs
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Script / Server.pm
1 package Catalyst::Script::Server;
2
3 BEGIN {
4     $ENV{CATALYST_ENGINE} ||= 'HTTP';
5     require Catalyst::Engine::HTTP;
6 }
7
8 use Moose;
9 use MooseX::Types::Common::Numeric qw/PositiveInt/;
10 use MooseX::Types::Moose qw/ArrayRef Str Bool Int RegexpRef/;
11 use Catalyst::Utils;
12 use namespace::autoclean;
13
14 with 'Catalyst::ScriptRole';
15
16 has debug => (
17     traits        => [qw(Getopt)],
18     cmd_aliases   => 'd',
19     isa           => Bool,
20     is            => 'ro',
21     documentation => q{Force debug mode},
22 );
23
24 has host => (
25     traits        => [qw(Getopt)],
26     cmd_aliases   => 'h',
27     isa           => Str,
28     is            => 'ro',
29     # N.B. undef (the default) means we bind on all interfaces on the host.
30     documentation => 'Specify a hostname or IP on this host for the server to bind to',
31 );
32
33 has fork => (
34     traits        => [qw(Getopt)],
35     cmd_aliases   => 'f',
36     isa           => Bool,
37     is            => 'ro',
38     default       => 0,
39     documentation => 'Fork the server to be able to serve multiple requests at once',
40 );
41
42 has port => (
43     traits        => [qw(Getopt)],
44     cmd_aliases   => 'p',
45     isa           => PositiveInt,
46     is            => 'ro',
47     default       => sub {
48         Catalyst::Utils::env_value(shift->application_name, 'port') || 3000
49     },
50     documentation => 'Specify a different listening port (to the default port 3000)',
51 );
52
53 has pidfile => (
54     traits        => [qw(Getopt)],
55     cmd_aliases   => 'pid',
56     isa           => Str,
57     is            => 'ro',
58     documentation => 'Specify a pidfile',
59 );
60
61 has keepalive => (
62     traits        => [qw(Getopt)],
63     cmd_aliases   => 'k',
64     isa           => Bool,
65     is            => 'ro',
66     default       => 0,
67     documentation => 'Support keepalive',
68 );
69
70 has background => (
71     traits        => [qw(Getopt)],
72     cmd_aliases   => 'bg',
73     isa           => Bool,
74     is            => 'ro',
75     default       => 0,
76     documentation => 'Run in the background',
77 );
78
79 has restart => (
80     traits        => [qw(Getopt)],
81     cmd_aliases   => 'r',
82     isa           => Bool,
83     is            => 'ro',
84     default       => sub {
85         Catalyst::Utils::env_value(shift->application_name, 'reload') || 0;
86     },
87     documentation => 'use Catalyst::Restarter to detect code changes and restart the application',
88 );
89
90 has restart_directory => (
91     traits        => [qw(Getopt)],
92     cmd_aliases   => [ 'rdir', 'restartdirectory' ],
93     isa           => ArrayRef[Str],
94     is            => 'ro',
95     documentation => 'Restarter directory to watch',
96     predicate     => '_has_restart_directory',
97 );
98
99 has restart_delay => (
100     traits        => [qw(Getopt)],
101     cmd_aliases   => 'rd',
102     isa           => Int,
103     is            => 'ro',
104     documentation => 'Set a restart delay',
105     predicate     => '_has_restart_delay',
106 );
107
108 {
109     use Moose::Util::TypeConstraints;
110
111     my $tc = subtype as RegexpRef;
112     coerce $tc, from Str, via { qr/$_/ };
113
114     MooseX::Getopt::OptionTypeMap->add_option_type_to_map($tc => '=s');
115
116     has restart_regex => (
117         traits        => [qw(Getopt)],
118         cmd_aliases   => 'rr',
119         isa           => $tc,
120         coerce        => 1,
121         is            => 'ro',
122         documentation => 'Restart regex',
123         predicate     => '_has_restart_regex',
124     );
125 }
126
127 has follow_symlinks => (
128     traits        => [qw(Getopt)],
129     cmd_aliases   => 'sym',
130     isa           => Bool,
131     is            => 'ro',
132     default       => 0,
133     documentation => 'Follow symbolic links',
134     predicate     => '_has_follow_symlinks',
135 );
136
137 sub _restarter_args {
138     my $self = shift;
139
140     return (
141         argv => $self->ARGV,
142         start_sub => sub { $self->_run_application },
143         ($self->_has_follow_symlinks   ? (follow_symlinks => $self->follow_symlinks)   : ()),
144         ($self->_has_restart_delay     ? (sleep_interval  => $self->restart_delay)     : ()),
145         ($self->_has_restart_directory ? (directories     => $self->restart_directory) : ()),
146         ($self->_has_restart_regex     ? (filter          => $self->restart_regex)     : ()),
147     );
148 }
149
150 has restarter_class => (
151     is => 'ro',
152     isa => Str,
153     lazy => 1,
154     default => sub {
155         my $self = shift;
156         Catalyst::Utils::env_value($self->application_name, 'RESTARTER') || 'Catalyst::Restarter';
157     }
158 );
159
160 sub run {
161     my $self = shift;
162
163     local $ENV{CATALYST_DEBUG} = 1
164         if $self->debug;
165
166     if ( $self->restart ) {
167         die "Cannot run in the background and also watch for changed files.\n"
168             if $self->background;
169
170         # If we load this here, then in the case of a restarter, it does not
171         # need to be reloaded for each restart.
172         require Catalyst;
173
174         # If this isn't done, then the Catalyst::Devel tests for the restarter
175         # fail.
176         $| = 1 if $ENV{HARNESS_ACTIVE};
177
178         Catalyst::Utils::load_class($self->restarter_class);
179
180         my $subclass = $self->restarter_class->pick_subclass;
181
182         my $restarter = $subclass->new(
183             $self->_restarter_args()
184         );
185
186         $restarter->run_and_watch;
187     }
188     else {
189         $self->_run_application;
190     }
191
192
193 }
194
195 sub _application_args {
196     my ($self) = shift;
197     return (
198         $self->port,
199         $self->host,
200         {
201            argv => $self->ARGV,
202            map { $_ => $self->$_ } qw/
203                 fork
204                 keepalive
205                 background
206                 pidfile
207                 keepalive
208                 follow_symlinks
209             /,
210         },
211     );
212 }
213
214 __PACKAGE__->meta->make_immutable;
215
216 1;
217
218 =head1 NAME
219
220 Catalyst::Script::Server - Catalyst test server
221
222 =head1 SYNOPSIS
223
224  myapp_server.pl [options]
225
226  Options:
227    -d     --debug          force debug mode
228    -f     --fork           handle each request in a new process
229                       (defaults to false)
230           --help           display this help and exits
231    -h     --host           host (defaults to all)
232    -p     --port           port (defaults to 3000)
233    -k     --keepalive      enable keep-alive connections
234    -r     --restart        restart when files get modified
235                        (defaults to false)
236    --rd   --restart_delay  delay between file checks
237                       (ignored if you have Linux::Inotify2 installed)
238    --rr   --restart_regex  regex match files that trigger
239                       a restart when modified
240                       (defaults to '\.yml$|\.yaml$|\.conf|\.pm$')
241    --rdir --restart_directory  the directory to search for
242                       modified files, can be set multiple times
243                       (defaults to '[SCRIPT_DIR]/..')
244    --sym  --follow_symlinks   follow symlinks in search directories
245                       (defaults to false. this is a no-op on Win32)
246    --bg   --background        run the process in the background
247    --pid  --pidfile           specify filename for pid file
248
249  See also:
250    perldoc Catalyst::Manual
251    perldoc Catalyst::Manual::Intro
252
253 =head1 DESCRIPTION
254
255 Run a Catalyst test server for this application.
256
257 =head1 AUTHORS
258
259 Catalyst Contributors, see Catalyst.pm
260
261 =head1 COPYRIGHT
262
263 This library is free software. You can redistribute it and/or modify
264 it under the same terms as Perl itself.
265
266 =cut