Sep 22

One of the traditional problems with mod_perl development is getting the server to recognize module changes, without restarting after every change. I’m thinking about an improved solution for this.

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. (EDIT: Dave Rolsky points out that this is fixed now under some OS’s.) 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. Finally, you are still ultimately waiting for a full restart.

3. MaxRequestsPerChild=1

Perrin Harkins 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: The Pied Piper

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.

Going to try to implement this as a plugin in Server::Control. Will see how it goes.


** – 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.

Sep 01

I’ve been thinking about what version 2.0 of Mason might look like. It’s been seven years since the last major version (1.10), and a lot has changed in the Perl world since then!

This is an initial brainstorm. Refinement and details to follow, and feedback is very much encouraged.

Name

  • HTML::Mason -> Mason. I believe we are finally entitled to a top-level name. :) This will help separate the new Mason from the old.
  • MasonX:: for extensions? This is more problematic, as the MasonX:: namespace already has a number of modules that are specific to the current Mason. Regardless, it needs to be a short and convenient prefix.

Implementation

  • Moose. We will use Moose for all classes. Moose represents a fundamentally different way of developing Perl, and it was the catalyst that started me thinking about a new Mason. Many of the remaining items in this list fall out of, or are enhanced by, Moosification.
  • Components will be classes. Components started out as subroutines, then became objects. The logical next step is for each component to be its own Moose subclass. This will allow components to benefit from true OO techniques (methods, attributes, roles), instead of Mason’s current painful pseudo-OO.
    • The entire component will be placed inside a MooseX::Declare class block, with a class name auto-generated from the component path.
    • The main component body – the content and the inline Perl sections – will be placed into a main method.
    • Calling a component (via <& &> or $m->comp) will mean creating a new instance of the component class, and calling its main method. Component call parameters will be passed to the constructor. Have to watch for performance impacts here.
    • A $self variable is automatically available, assigned to the component instance.
    • One of <%args> or <%attr> will be used to generate Moose attributes, rather than subroutine parameters. There will still be some syntactic sugar, but the section will have access to the full power of attributes. e.g.
      <%args>
         foo
         bar => (default => 5)
         baz => (default => 5, isa => 'Int')
         </%args>

      The advantage of attributes over parameters is that other methods in the component will have access to those values, something that is painful to deal with right now.

  • Subcomponents will become methods. <%def> and <%method> are currently implemented as their own component objects inside the main component. There was never a particularly good reason to do this other than that it seemed like a neat idea, and over the years it has proved more frustrating than helpful – e.g. $m->current_comp and $m->caller sometimes defy expectation. Now that components will be classes, it makes sense for a subcomponent to be just another method alongside main.
  • Autohandlers will be superclasses. Components will truly inherit from their autohandlers now. e.g. they’ll be able to call methods in the autohandler, a great way to share code within a hierarchy of components.
  • Smaller core, more extensions. As with other modern Perl frameworks, we should move as much as we can from the core to extensions, where we can do so without overly sacrificing ease of use, performance, etc.

Syntax

  • Same core syntax. The core syntax will be mostly the same – <% %> blocks, <%perl> and <%init> sections, %-lines. I do sometimes regret not going with the industry-standard <%= %> for expressions, so that <% %> could be used for non-expression Perl; but at this point <% $foo %> may be too deeply embedded in my brain to change it.
  • <%once> becomes <%class>. The <%class> section will contain code to be placed in the class definition outside the main method: ‘use’ statements, pure-Perl methods, utility subroutines, pragmas etc.
  • Automatic newline removal. Obvious newlines should be removed by default, so that components can be spaced neatly without adding gratuitous newlines to the output.
  • Consolidated filter syntax. Mason has several kinds of content filters: <%filter> section, components with content, and escapes (e.g. |h). All of these filtering methods should be consolidated under a single implementation, if not a single syntax. In addition, we need a way to create new content filters with Perl methods and use them on blocks. Standard filters could be installed on the main component class, and more specific filters on individual components. Example:
  • <%class>
       filter repeat ($times) {
           my ($self, $content) = @_;
           return $content x $times;
       }
       </%class>
    
       ...
    
       <% repeat (3) { %>
       blah blah
       <% } %>

New features

  • More powerful controller mechanisms. Mason has controller mechanisms – dhandler, autohandler, and the resolver – that were innovative once but are now underpowered. I don’t believe (as some do) that Mason should get out of the controller business – I actually like having my “C” and “V” in the same place. Mason just needs to provide easy access to the same powerful routing techniques that are used in modern web frameworks, e.g. via Path::Dispatcher or Path::Router. For example, an autohandler or dhandler or other special file could indicate how paths under that directory should be routed – still have to work out the syntactic details. Of course, nothing will prevent people from using an MVC framework’s routing and treating Mason like a controller-less template language.
  • Logging. Mason will log generously with different levels and categories via Log::Any. This was supposed to be put into Mason 1.x years ago but never made it…
  • Output placeholders. Support the insertion of placeholders whose values can be supplied by code further along in the request. This is motivated by HTML head elements, like title, that you want to output in the top template but determine in a more specific page component.

New extensions

  • MasonX::Tidy and MasonX::Critic. Tidying and criticizing specific to Mason components, analagous to what perltidy and perlcritic do for Perl.
  • MasonX::Safe. Use static code analysis (PPI) to restrict the set of Perl operations that could be executed in a set of Mason components. In the spirit of, but less draconian and broken than, Safe. Useful for environments when non-Perl-programmers are modifying components, or to give the “don’t do too much in components” philosophy some teeth. Intended for friendly policy enforcement, not airtight security.

What can be deprecated/eliminated

  • Web features. Mason has always ambiguously straddled the line between template language and web framework. This was out of necessity — when Mason was created, mod_perl was the only “web framework” in Perl. With the advent of web frameworks like Catalyst, Jifty and CGI::Application, and interfaces like PSGI/Plack, Mason no longer needs to occupy the web space. It should strive to simply be a great templating system that is easy to plug into various web frameworks. This means we can eliminate, among other things, the ApacheHandler and CGIHandler classes from the core.
  • Plugin API. In 1.3 we added a custom Mason plugin API, but Moose method modifiers and roles are a far better and more industry-standard way of supporting plugins.
  • <%cleanup> section. <%cleanup> has always been of dubious value because it is not guaranteed to run in case of an abnormal exit from the component. Now that components are classes, a DESTROY method in the <%class> section will be a more appropriate and functional way to perform cleanup.
  • <%shared> section. Since the various methods in a component are now part of the same class and share attributes, there is no reason to have <%shared>.
  • <%attr> or <%args> section. We only need to retain one of these to represent class attributes; the other can be eliminated.
  • <%method> or <%def> section. Perl methods will now be easy to define in the <%class> section. It will still be useful to define methods that produce output, but we only need one of these sections.
  • Non-CHI cache APIs. Eliminate the Cache::Cache and 1.0 APIs, and just support CHI.

What will be kept, begrudgingly

  • Components returning values. There are some cleanliness arguments for eliminating the ability of components to return values – one should use methods instead, etc. But I think this feature is too frequently used to discard. This is something to discourage in the docs and for MasonX::Critic to complain about. :)

What do you think?

Mason developers, let me hear your feedback and ideas.

preload preload preload