1 package Catalyst::Restarter;
5 use Cwd qw( abs_path );
6 use File::ChangeNotify;
9 use namespace::clean -except => 'meta';
25 isa => 'File::ChangeNotify::Watcher',
43 defined $ENV{CATALYST_RESTARTER}
44 ? $ENV{CATALYST_RESTARTER}
49 $subclass = 'Catalyst::Restarter::' . $subclass;
61 delete $p->{start_sub};
63 $p->{filter} ||= qr/(?:\/|^)(?![.#_]).+(?:\.yml$|\.yaml$|\.conf|\.pm)$/;
65 my $app_root = abs_path( File::Spec->catdir( $FindBin::Bin, '..' ) );
67 # Monitor application root dir
68 $p->{directories} ||= $app_root;
70 # exclude t/, root/ and hidden dirs
72 File::Spec->catdir($app_root, 't'),
73 File::Spec->catdir($app_root, 'root'),
74 qr(/\.[^/]*/?$), # match hidden dirs
77 # keep filter regexp to make shure we don't restart on deleted
78 # files or directories where we can't check -d
79 $self->_filter( $p->{filter} );
81 # We could make this lazily, but this lets us check that we
82 # received valid arguments for the watcher up front.
83 $self->_watcher( File::ChangeNotify->instantiate_watcher( %{$p} ) );
89 $self->_fork_and_start;
91 return unless $self->_child;
93 $self->_restart_on_changes;
96 sub _restart_on_changes {
99 # We use this loop in order to avoid having _handle_events() call back
100 # into this method. We used to do that, and the end result was that stack
101 # traces became longer and longer with every restart. Using this loop, the
102 # portion of the stack trace that covers this code does not grow.
104 my @events = $self->_watcher->wait_for_events();
105 $self->_handle_events(@events);
114 for my $event (@events) {
115 my $path = $event->path();
116 my $type = $event->type();
117 if ( ( $type ne 'delete' && -f $path )
118 || ( $type eq 'delete' && $path =~ $self->_filter ) )
120 push @files, { path => $path, type => $type };
126 print STDERR "Saw changes to the following files:\n";
129 my $path = $f->{path};
130 my $type = $f->{type};
131 print STDERR " - $path ($type)\n";
135 print STDERR "Attempting to restart the server\n\n";
139 $self->_fork_and_start;
149 __PACKAGE__->meta->make_immutable;
157 Catalyst::Restarter - Uses File::ChangeNotify to check for changed files and restart the server
161 my $class = Catalyst::Restarter->pick_subclass;
163 my $restarter = $class->new(
164 directories => '/path/to/MyApp',
165 regex => '\.yml$|\.yaml$|\.conf|\.pm$',
166 start_sub => sub { ... }
169 $restarter->run_and_watch;
173 This is the base class for all restarters, and it also provide
174 functionality for picking an appropriate restarter subclass for a
177 This class uses L<File::ChangeNotify> to watch one or more directories
178 of files and restart the Catalyst server when any of those files
185 Returns the name of an appropriate subclass for the given platform.
187 =head2 new ( start_sub => sub { ... }, ... )
189 This method creates a new restarter object, but should be called on a
190 subclass, not this class.
192 The "start_sub" argument is required. This is a subroutine reference
193 that can be used to start the Catalyst server.
197 This method forks, starts the server in a child process, and then
198 watched for changed files in the parent. When files change, it kills
199 the child, forks again, and starts a new server.
203 L<Catalyst>, <File::ChangeNotify>
207 Catalyst Contributors, see Catalyst.pm
211 This program is free software, you can redistribute it and/or modify
212 it under the same terms as Perl itself.