Bring copyright statement in sync with the other packages
[catagits/Catalyst-Devel.git] / lib / Catalyst / Restarter.pm
CommitLineData
8462f41e 1package Catalyst::Restarter;
2
3use Moose;
4
ffbcd711 5use Cwd qw( abs_path );
a13b99da 6use File::ChangeNotify;
ffbcd711 7use FindBin;
8462f41e 8use namespace::clean -except => 'meta';
9
b8e3feb1 10has start_sub => (
8462f41e 11 is => 'ro',
12 isa => 'CodeRef',
13 required => 1,
14);
15
5ad5350a 16has argv => (
17 is => 'ro',
18 isa => 'ArrayRef',
19 required => 1,
20);
21
8462f41e 22has _watcher => (
23 is => 'rw',
a13b99da 24 isa => 'File::ChangeNotify::Watcher',
8462f41e 25);
26
27has _child => (
28 is => 'rw',
29 isa => 'Int',
30);
31
2e9609df 32sub pick_subclass {
33 my $class = shift;
34
35 my $subclass;
36 $subclass =
37 defined $ENV{CATALYST_RESTARTER}
38 ? $ENV{CATALYST_RESTARTER}
39 : $^O eq 'MSWin32'
40 ? 'Win32'
41 : 'Forking';
42
43 $subclass = 'Catalyst::Restarter::' . $subclass;
44
45 eval "use $subclass";
46 die $@ if $@;
47
48 return $subclass;
49}
50
8462f41e 51sub BUILD {
52 my $self = shift;
53 my $p = shift;
54
b8e3feb1 55 delete $p->{start_sub};
8462f41e 56
23f28bf0 57 $p->{filter} ||= qr/(?:\/|^)(?![.#_]).+(?:\.yml$|\.yaml$|\.conf|\.pm)$/;
ffbcd711 58 $p->{directories} ||= abs_path( File::Spec->catdir( $FindBin::Bin, '..' ) );
a13b99da 59
8462f41e 60 # We could make this lazily, but this lets us check that we
61 # received valid arguments for the watcher up front.
a13b99da 62 $self->_watcher( File::ChangeNotify->instantiate_watcher( %{$p} ) );
8462f41e 63}
64
65sub run_and_watch {
66 my $self = shift;
67
68 $self->_fork_and_start;
69
70 return unless $self->_child;
71
72 $self->_restart_on_changes;
73}
74
8462f41e 75sub _restart_on_changes {
76 my $self = shift;
77
868361e8 78 # We use this loop in order to avoid having _handle_events() call back
79 # into this method. We used to do that, and the end result was that stack
0fde42f0 80 # traces became longer and longer with every restart. Using this loop, the
81 # portion of the stack trace that covers this code does not grow.
868361e8 82 while (1) {
83 my @events = $self->_watcher->wait_for_events();
84 $self->_handle_events(@events);
85 }
7f564068 86}
8462f41e 87
a13b99da 88sub _handle_events {
89 my $self = shift;
90 my @events = @_;
8462f41e 91
7f564068 92 print STDERR "\n";
93 print STDERR "Saw changes to the following files:\n";
a13b99da 94
95 for my $event (@events) {
96 my $path = $event->path();
97 my $type = $event->type();
98
99 print STDERR " - $path ($type)\n";
100 }
101
7f564068 102 print STDERR "\n";
103 print STDERR "Attempting to restart the server\n\n";
8462f41e 104
7f564068 105 $self->_kill_child;
8462f41e 106
7f564068 107 $self->_fork_and_start;
8462f41e 108}
109
02758cf8 110sub DEMOLISH {
111 my $self = shift;
112
113 $self->_kill_child;
114}
115
8462f41e 116__PACKAGE__->meta->make_immutable;
117
1181;
83d2d4a4 119
120__END__
121
122=head1 NAME
123
b8e3feb1 124Catalyst::Restarter - Uses File::ChangeNotify to check for changed files and restart the server
83d2d4a4 125
126=head1 SYNOPSIS
127
36ff1319 128 my $class = Catalyst::Restarter->pick_subclass;
129
130 my $restarter = $class->new(
b8e3feb1 131 directories => '/path/to/MyApp',
132 regex => '\.yml$|\.yaml$|\.conf|\.pm$',
133 start_sub => sub { ... }
83d2d4a4 134 );
135
b8e3feb1 136 $restarter->run_and_watch;
83d2d4a4 137
138=head1 DESCRIPTION
139
36ff1319 140This is the base class for all restarters, and it also provide
141functionality for picking an appropriate restarter subclass for a
142given platform.
143
b8e3feb1 144This class uses L<File::ChangeNotify> to watch one or more directories
145of files and restart the Catalyst server when any of those files
146changes.
83d2d4a4 147
148=head1 METHODS
149
36ff1319 150=head2 pick_subclass
151
152Returns the name of an appropriate subclass for the given platform.
153
b8e3feb1 154=head2 new ( start_sub => sub { ... }, ... )
155
36ff1319 156This method creates a new restarter object, but should be called on a
157subclass, not this class.
83d2d4a4 158
b8e3feb1 159The "start_sub" argument is required. This is a subroutine reference
160that can be used to start the Catalyst server.
83d2d4a4 161
b8e3feb1 162=head2 run_and_watch
83d2d4a4 163
b8e3feb1 164This method forks, starts the server in a child process, and then
165watched for changed files in the parent. When files change, it kills
166the child, forks again, and starts a new server.
83d2d4a4 167
168=head1 SEE ALSO
169
b8e3feb1 170L<Catalyst>, <File::ChangeNotify>
83d2d4a4 171
172=head1 AUTHORS
173
174Catalyst Contributors, see Catalyst.pm
175
176=head1 COPYRIGHT
177
178This program is free software, you can redistribute it and/or modify
179it under the same terms as Perl itself.
180
181=cut