merge from trunk
[catagits/Catalyst-Devel.git] / lib / Catalyst / Restarter.pm
CommitLineData
8462f41e 1package Catalyst::Restarter;
2
3use Moose;
4
5use Catalyst::Watcher;
6use File::Spec;
7use FindBin;
8use namespace::clean -except => 'meta';
9
10has restart_sub => (
11 is => 'ro',
12 isa => 'CodeRef',
13 required => 1,
14);
15
16has _watcher => (
17 is => 'rw',
18 isa => 'Catalyst::Watcher',
19);
20
21has _child => (
22 is => 'rw',
23 isa => 'Int',
24);
25
26sub BUILD {
27 my $self = shift;
28 my $p = shift;
29
30 delete $p->{restart_sub};
31
32 # We could make this lazily, but this lets us check that we
33 # received valid arguments for the watcher up front.
34 $self->_watcher( Catalyst::Watcher->new( %{$p} ) );
35}
36
37sub run_and_watch {
38 my $self = shift;
39
40 $self->_fork_and_start;
41
42 return unless $self->_child;
43
44 $self->_restart_on_changes;
45}
46
47sub _fork_and_start {
48 my $self = shift;
49
50 if ( my $pid = fork ) {
51 $self->_child($pid);
52 }
53 else {
54 $self->restart_sub->();
55 }
56}
57
58sub _restart_on_changes {
59 my $self = shift;
60
61 my $watcher = $self->_watcher;
62
63 while (1) {
64 my @files = $watcher->find_changed_files
65 or next;
66
67 print STDERR "Saw changes to the following files:\n";
68 print STDERR " - $_->{file} ($_->{status})\n" for @files;
69 print STDERR "\n";
70 print STDERR "Attempting to restart the server\n\n";
71
72 if ( $self->_child ) {
73 kill 2, $self->_child
74 or die "Cannot send INT to child (" . $self->_child . "): $!";
75 }
76
77 $self->_fork_and_start;
78
79 return unless $self->_child;
80 }
81}
82
83sub DEMOLISH {
84 my $self = shift;
85
86 if ( $self->_child ) {
87 kill 2, $self->_child;
88 }
89}
90
91__PACKAGE__->meta->make_immutable;
92
931;
83d2d4a4 94
95__END__
96
97=head1 NAME
98
99Catalyst::Restarter - Uses Catalyst::Watcher to check for changed files and restart the server
100
101=head1 SYNOPSIS
102
103 my $watcher = Catalyst::Watcher->new(
104 directory => '/path/to/MyApp',
105 regex => '\.yml$|\.yaml$|\.conf|\.pm$',
106 interval => 3,
107 );
108
109 while (1) {
110 my @changed_files = $watcher->watch();
111 }
112
113=head1 DESCRIPTION
114
115This class monitors a directory of files for changes made to any file
116matching a regular expression. It correctly handles new files added to the
117application as well as files that are deleted.
118
119=head1 METHODS
120
121=head2 new ( directory => $path [, regex => $regex, delay => $delay ] )
122
123Creates a new Watcher object.
124
125=head2 find_changed_files
126
127Returns a list of files that have been added, deleted, or changed
128since the last time watch was called. Each element returned is a hash
129reference with two keys. The C<file> key contains the filename, and
130the C<status> key contains one of "modified", "added", or "deleted".
131
132=head1 SEE ALSO
133
134L<Catalyst>, L<Catalyst::Restarter>, <File::Modified>
135
136=head1 AUTHORS
137
138Catalyst Contributors, see Catalyst.pm
139
140=head1 COPYRIGHT
141
142This program is free software, you can redistribute it and/or modify
143it under the same terms as Perl itself.
144
145=cut