Catalyst の開発版の Helper
PowerBook にインストールして使ってる Catalyst は 5.33 なんだけど、このところすごい勢いでバージョンアップしているらしい。
それはさておき、svn から開発版のソースを拾ってきて Catalyst::Helper のコードを眺めていたら server.pl がずいぶんパワーアップしていることに気づく。
Options: -d -debug force debug mode -f -fork handle each request in a new process (defaults to false) -? -help display this help and exits -host host (defaults to all) -p -port port (defaults to 3000) -k -keepalive enable keep-alive connections -r -restart restart when files got modified (defaults to false) -rd -restartdelay delay between file checks -rr -restartregex regex match files that trigger a restart when modified (defaults to '?.yml$|?.yaml$|?.pm$')
-r
で restart したりできるというのは前にちょっと聞いたけど、fork できるようになってたり keepalive を ON/OFF できたり、あと -rd
とか -rr
とかオプションが増えてる。
あと、Helper の末尾の方にバイナリの hex dump がw $helper->_mk_images
で Catalyst のロゴとかバナーとか favicon とかが作られるみたいなんだけど、Catalyst::Helper は __DATA__
にヘルパーの中身を書いてて、んでバイナリが混ざってるという。うひょ。
ちなみに開発版は、
svn co http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst Catalyst
で取れます。(via http://www.lost-season.jp/mt/2005/10/200510182.html)
Catalyst::Engine::HTTP::Restarter における自動再起動サーバーの実装
前の話の続き。新しい server.pl は -r オプションをつけたときに、自動的にファイルの修正を検知して再起動してくれる機能が付いてます。
いままでの server.pl だと、デーモン上で perl が永続化してるためにモジュールを書き換えてもそれが再読込されず、一度 ^C で止めてまた起動とかする必要がありました。で、それが必要なくなったと。先日 Rails を試しにいじってたんですが、Rails 付属の WEBrick なサーバーは、クラスの更新も検知してくれてスゲー便利だったので、server.pl がこの仕様になったのはすごくいいです。
どういう実装でこれを実現してるのかなーと思って見てたんですが、やっぱりそこは Catalyst、ちょっと面白い実装になってました。手元にある 5.33 からだと
の二つのクラスが追加されてます。
Watcher は File::Modified を使って、指定したディレクトリの中の .pm ファイルの mtime を監視するクラスで、変更を検知した際にモジュールのシンタックスチェックもしてくれるユーティリティのような役割。特に Catalyst に結合してる感じではないです。
一方の Catalyst::Engine::HTTP::Restarter は Catalyst::Engine::HTTP を継承しています。
- app_server.pl から
Catalyst::Engine::HTTP::Restarter->run
が呼ばれる - fork する
- 親は
$self->NEXT::run
でCatalyst::Engine::HTTP->run
へ redispatch されデーモンになり HTTP リクエストを待機 - 子は Watcher インスタンスを作って無限ループの中でモジュールの変更を監視する。
- 子はモジュールの変更を関知するとソケットで親デーモンの待機ポートに接続し、HTTP で 'RESTART' というメソッドを送信し終了する
- 親は RESTART メソッドを受け取ると自分自身を実行しているスクリプトを exec して再度自分を実行する
という流れで処理が進んでいきます。ファイルの変更を感知するための処理を NEXT と fork で別プロセスに分離してるのと、子から親へのシグナルに HTTP を使ってるあたりが面白いですね。