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