Return-Path: Delivered-To: apmail-perl-modperl-archive@www.apache.org Received: (qmail 26155 invoked from network); 11 Sep 2009 21:27:22 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 11 Sep 2009 21:27:22 -0000 Received: (qmail 8401 invoked by uid 500); 11 Sep 2009 21:27:20 -0000 Delivered-To: apmail-perl-modperl-archive@perl.apache.org Received: (qmail 8377 invoked by uid 500); 11 Sep 2009 21:27:20 -0000 Mailing-List: contact modperl-help@perl.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list modperl@perl.apache.org Received: (qmail 8369 invoked by uid 99); 11 Sep 2009 21:27:20 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 11 Sep 2009 21:27:20 +0000 X-ASF-Spam-Status: No, hits=0.2 required=10.0 tests=RCVD_IN_DNSWL_LOW,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (athena.apache.org: 66.111.4.25 is neither permitted nor denied by domain of swartz@pobox.com) Received: from [66.111.4.25] (HELO out1.smtp.messagingengine.com) (66.111.4.25) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 11 Sep 2009 21:27:09 +0000 Received: from compute1.internal (compute1.internal [10.202.2.41]) by gateway1.messagingengine.com (Postfix) with ESMTP id E2B4A644B3 for ; Fri, 11 Sep 2009 17:26:46 -0400 (EDT) Received: from heartbeat1.messagingengine.com ([10.202.2.160]) by compute1.internal (MEProxy); Fri, 11 Sep 2009 17:26:46 -0400 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=messagingengine.com; h=subject:from:content-type:message-id:date:to:content-transfer-encoding:mime-version; s=smtpout; bh=GRP57RV0fxwBKXS1JwhiACXvZ18=; b=i+NXUGmKLx5nSz8lWqUh2YqjQZfF+2LgezMeJzFYQz9G+6sXRpinR12ZRBFtSZp8XCTaEWlxjRggXO4XCcj4+lTGRFjyKXrXj1XvjF+MmT4ovwWLhAhFKhrT5dDZAKj8lsmpmz6wj9+lEd9mmSSe6ozqWOFof6KlNa/GoBcW8jo= X-Sasl-enc: ZAp+1eaQt42xcLDdpNAtyytIYmT8gy8/oM60Gb5pd1BM 1252704406 Received: from [192.168.1.102] (dsl081-241-091.sfo1.dsl.speakeasy.net [64.81.241.91]) by mail.messagingengine.com (Postfix) with ESMTPSA id 525A3699E0 for ; Fri, 11 Sep 2009 17:26:46 -0400 (EDT) Subject: a better way to recognize module changes From: Jonathan Swartz Content-Type: text/plain; charset=us-ascii; format=flowed; delsp=yes Message-Id: <2491C7E6-3D88-43E2-844D-F5BC591FEAFC@pobox.com> Date: Fri, 11 Sep 2009 14:26:44 -0700 To: modperl@perl.apache.org Content-Transfer-Encoding: 7bit Mime-Version: 1.0 (Apple Message framework v1076) X-Mailer: Apple Mail (2.1076) X-Virus-Checked: Checked by ClamAV on apache.org I'm thinking about an improved solution to recognizing module changes in a running server, without restarting the server. These are the solutions I know about: 1) Apache2::Reload / Module::Reload These check whether modules have changed on each request, and if so, clear their symbols and reload them inside the process. Problem: some modules fail to reload properly. Sometimes the failure is intermittent, depending on the order of module loading and other esoteric details. Moose and ORM modules seem particularly prone to reload failures. For me, this level of unpredictability makes *::Reload too frustrating to use. 2) Catalyst auto-restart Catalyst has an engine (Catalyst::Engine::HTTP::Prefork::Restarter) which forks off a "watcher" process that waits for your modules to change. When they change, it restarts the server. The usual effect is that, between the time you hit "save" in your editor and reload your page, the server has restarted or at least begun restarting. Problems: Doesn't work well if you make a few changes in a row; the restart only captures your first change. Bad user experience if there's an error in your module; you have to realize the server has died, find the error message in some shell or log, and manually start up the server again. 3) Perrin's MaxRequestsPerChild=1 Perrin recently alerted me to the MaxRequestsPerChild=1 technique. That is, set MaxRequestsPerChild to 1, then load any potentially- changing modules in the *child*, not the parent (obviously only for development environments). Each request will hit a fresh child server, which will load all of your potentially-changing modules anew. This is the nicest solution I've seen so far. The only problem I can see is its performance - each potentially-changing module has to be loaded on each request. ** 4) My idea: Combine 2 and 3 As in 3, load any potentially-changing modules in the child. Leave MaxRequestsPerChild alone. As in 2, fork off a "watcher" process that waits for your modules to change. When they change, kill all the server's children explicitly. The end result is that you get reasonable performance when your modules don't change (e.g. when you are only futzing with templates), but when modules do change, you should see the effects immediately. This should be able to work with mod_perl, fastcgi, Net::Server, etc., as long as the parent server responds appropriately to the killing of all its children (by launching new ones). Apache, at least, seems to be ok with this. What do people think? Is this worth codifying in a module, or does something like this already exist? Thanks for any feedback Jon ** - You can try to load things only on demand, but often mod_perl code is written without 'use' statements as it assumes everything is loaded in the parent. You can also try to minimize the number of potentially-changing modules, but then you run the risk of leaving something off and having to adjust it and restart.