Revamped how the restarter stuff works so it's totally separate from
[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;