From: Tomas Doran Date: Sun, 15 Feb 2009 05:22:59 +0000 (+0000) Subject: Make restarters immutable handling less naive + tests X-Git-Tag: 5.80001~98 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=commitdiff_plain;h=65b708a697de08be81bf212704d495e8cad41ed2;hp=7bf342486846ff902822a01c8df4689bfa7a6a6f Make restarters immutable handling less naive + tests --- diff --git a/Changes b/Changes index 11059bd..17f7b7a 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,11 @@ # This file documents the revision history for Perl extension Catalyst. - - Naive implementation of making packages mutable before restarting so - that restarter works with native Moose apps using immutable (t0m) + - Non-naive implementation of making mutable on restart using + B::Hooks::OP::Check::StashChange if installed (t0m) + - Tests for this (t0m) + - Naive implementation of making all components mutable in the + forked restart watcher process so native Moose apps using + immutable restart correctly. (t0m) - Tests for this (t0m) - Bump Moose dependency to 0.70 so that we avoid nasty surprises with is_class_loaded and perl 5.80 when you Moosify MyApp.pm (t0m) diff --git a/Makefile.PL b/Makefile.PL index 15c1a81..cc00a09 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -34,6 +34,8 @@ requires 'URI' => '1.35'; requires 'Text::Balanced'; # core in 5.8.x but mentioned for completeness requires 'MRO::Compat'; +recommends 'B::Hooks::OP::Check::StashChange'; + test_requires 'Class::Data::Inheritable'; test_requires 'Test::MockObject'; diff --git a/lib/Catalyst/Engine/HTTP/Restarter/Watcher.pm b/lib/Catalyst/Engine/HTTP/Restarter/Watcher.pm index 18ce316..3690877 100644 --- a/lib/Catalyst/Engine/HTTP/Restarter/Watcher.pm +++ b/lib/Catalyst/Engine/HTTP/Restarter/Watcher.pm @@ -7,6 +7,18 @@ use File::Find; use File::Modified; use File::Spec; use Time::HiRes qw/sleep/; +use Moose::Util qw/find_meta/; +use namespace::clean -except => 'meta'; + +BEGIN { + # If we can detect stash changes, then we do magic + # to make their metaclass mutable (if they have one) + # so that restarting works as expected. + eval { require B::Hooks::OP::Check::StashChange; }; + *DETECT_PACKAGE_COMPILATION = $@ + ? sub () { 0 } + : sub () { 1 } +} has delay => (is => 'rw'); has regex => (is => 'rw'); @@ -15,10 +27,8 @@ has directory => (is => 'rw'); has watch_list => (is => 'rw'); has follow_symlinks => (is => 'rw'); -no Moose; - sub BUILD { - shift->_init; + shift->_init; } sub _init { @@ -126,7 +136,18 @@ sub _index_directory { sub _test { my ( $self, $file ) = @_; - delete $INC{$file}; + my $id; + if (DETECT_PACKAGE_COMPILATION) { + $id = B::Hooks::OP::Check::StashChange::register(sub { + my ($new, $old) = @_; + my $meta = find_meta($new); + if ($meta) { + $meta->make_mutable if $meta->is_immutable; + } + }); + } + + delete $INC{$file}; # Remove from %INC so it will reload local $SIG{__WARN__} = sub { }; open my $olderr, '>&STDERR'; @@ -134,6 +155,8 @@ sub _test { eval "require '$file'"; open STDERR, '>&', $olderr; + B::Hooks::OP::Check::StashChange::unregister($id) if $id; + return ($@) ? $@ : 0; } diff --git a/t/lib/TestApp/Controller/Immutable/HardToReload.pm b/t/lib/TestApp/Controller/Immutable/HardToReload.pm new file mode 100644 index 0000000..774562a --- /dev/null +++ b/t/lib/TestApp/Controller/Immutable/HardToReload.pm @@ -0,0 +1,26 @@ +package TestApp::Controller::Immutable::HardToReload; +use Moose; +BEGIN { extends 'Catalyst::Controller' } +no Moose; +__PACKAGE__->meta->make_immutable; + +package # Standard PAUSE hiding technique + TestApp::Controller::Immutable::HardToReload::PAUSEHide; +use Moose; +BEGIN { extends 'Catalyst::Controller' } +no Moose; +__PACKAGE__->meta->make_immutable; + +# Not an inner package +package TestApp::Controller::Immutable2; +use Moose; +BEGIN { extends 'Catalyst::Controller' } +no Moose; +__PACKAGE__->meta->make_immutable; + +# Not even in the app namespace +package Frobnitz; +use Moose; +BEGIN { extends 'Catalyst::Controller' } +no Moose; +__PACKAGE__->meta->make_immutable; diff --git a/t/optional_http-server-restart.t b/t/optional_http-server-restart.t index c3bff4f..39f475a 100644 --- a/t/optional_http-server-restart.t +++ b/t/optional_http-server-restart.t @@ -13,6 +13,7 @@ use FindBin; use LWP::Simple; use IO::Socket; use IPC::Open3; +use Catalyst::Engine::HTTP::Restarter::Watcher; use Time::HiRes qw/sleep/; eval "use Catalyst::Devel 1.0;"; @@ -68,6 +69,9 @@ my @files = ( "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp/Controller/Immutable.pm", ); +push(@files, "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp/Controller/Immutable/HardToReload.pm") + if Catalyst::Engine::HTTP::Restarter::Watcher::DETECT_PACKAGE_COMPILATION(); + # change some files and make sure the server restarts itself NON_ERROR_RESTART: for ( 1 .. 20 ) {