<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Open Swartz</title>
	<atom:link href="http://www.openswartz.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.openswartz.com</link>
	<description>Perl and open source development</description>
	<lastBuildDate>Sun, 06 May 2012 14:14:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Memoize: Revisiting a twelve year old API</title>
		<link>http://www.openswartz.com/2012/05/06/memoize-revisiting-a-twelve-year-old-api/</link>
		<comments>http://www.openswartz.com/2012/05/06/memoize-revisiting-a-twelve-year-old-api/#comments</comments>
		<pubDate>Sun, 06 May 2012 14:14:18 +0000</pubDate>
		<dc:creator>Jonathan Swartz</dc:creator>
				<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.openswartz.com/?p=221</guid>
		<description><![CDATA[Memoization is a technique for optimizing a function over repeated calls. When you call the function, the return value is cached (based on the arguments passed) before being returned to you. Next time you call the function with the same arguments, you&#8217;ll get the value back immediately.
Memoize is the standard Perl memoization solution and after [...]]]></description>
			<content:encoded><![CDATA[<p><em>Memoization</em> is a technique for optimizing a function over repeated calls. When you call the function, the return value is cached (based on the arguments passed) before being returned to you. Next time you call the function with the same arguments, you&#8217;ll get the value back immediately.</p>
<p><a href="http://search.cpan.org/perldoc?Memoize">Memoize</a> is the standard Perl memoization solution and after twelve+ years still works well in the common case. However, since Perl caching support has come a long way, and memoization is just a specific form of caching, I wanted to try pairing memoization with modern cache features. Hence, <a href="http://search.cpan.org/perldoc?CHI::Memoize">CHI::Memoize</a>.</p>
<p>Here are some of the nice features that came out of this:</p>
<ul>
<li>The ability to cache to any of CHI&#8217;s other backends. e.g.
<pre><code>    memoize( 'func', driver =&gt; 'File', root_dir =&gt; '/path/to/cache' );
    memoize( 'func', driver =&gt; 'Memcached', servers =&gt; ["127.0.0.1:11211"] );
</code></pre>
</li>
<li>The ability to expire memoized values based on time or a condition. e.g.</p>
<pre><code>    memoize( 'func', expires_in =&gt; '1h' );
    memoize( 'func', expire_if =&gt; sub { ... } );
</code></pre>
</li>
<li>A better key normalizer. Memoize just joins the keys into a string, which doesn&#8217;t work for references/undef and can generate multiple keys for the same hash. In contrast, C<CHI::Memoize> relies on CHI&#8217;s <a href="http://search.cpan.org/perldoc?CHI#Key_transformations">automatic serialization</a> of non-scalar keys. So these will be memoized together:</p>
<pre><code>    memoized_function( a =&gt; 5, b =&gt; 6, c =&gt; { d =&gt; 7, e =&gt; 8 } );
    memoized_function( b =&gt; 6, c =&gt; { e =&gt; 8, d =&gt; 7 }, a =&gt; 5 );
</code></pre>
<p>and it&#8217;s easy to specify your own key, e.g. memoize on just the second and third arguments:</p>
<pre><code>    memoize( 'func', key =&gt; sub { $_[1], $_[2] } );
</code></pre>
</li>
</ul>
<p>Subsets of these features were already available <a href="http://search.cpan.org/perldoc?Memoize::Expire">in</a> <a href="http://search.cpan.org/perldoc?Memoize::ExpireLRU">separate</a> <a href="http://search.cpan.org/perldoc?Memoize::Memcached">distributions</a>, but not all in one place.</p>
<p>Now that this available I&#8217;m curious to see where I use it in place of the traditional get-and-set cache pattern.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.openswartz.com/2012/05/06/memoize-revisiting-a-twelve-year-old-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Poet: a web framework for Mason</title>
		<link>http://www.openswartz.com/2012/04/21/poet-a-web-framework-for-mason/</link>
		<comments>http://www.openswartz.com/2012/04/21/poet-a-web-framework-for-mason/#comments</comments>
		<pubDate>Sat, 21 Apr 2012 07:04:03 +0000</pubDate>
		<dc:creator>Jonathan Swartz</dc:creator>
				<category><![CDATA[Mason 2]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.openswartz.com/?p=212</guid>
		<description><![CDATA[I&#8217;m pleased to announce Poet, a modern Perl web framework designed especially for Mason developers.
Features include:


A common-sense directory hierarchy for web development


A configuration system that scales elegantly with multiple coders and multiple layers (development/production)


Integration with PSGI/Plack for server APIs and engines


Integration with Log::Log4perl for logging, wrapped with much simpler configuration


Integration with CHI for powerful and [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m pleased to announce <a href="http://search.cpan.org/perldoc?Poet">Poet</a>, a modern Perl web framework designed especially for <a href="http://search.cpan.org/perldoc?Mason">Mason</a> developers.</p>
<p>Features include:</p>
<ul>
<li>
<p>A common-sense <a href="http://search.cpan.org/perldoc?Poet::Manual::Intro#ENVIRONMENT">directory hierarchy</a> for web development</p>
</li>
<li>
<p>A <a href="http://search.cpan.org/perldoc?Poet::Conf">configuration system</a> that scales elegantly with multiple coders and multiple layers (development/production)</p>
</li>
<li>
<p>Integration with <a href="http://search.cpan.org/perldoc?PSGI">PSGI</a>/<a href="http://search.cpan.org/perldoc?Plack">Plack</a> for server APIs and engines</p>
</li>
<li>
<p>Integration with <a href="http://search.cpan.org/perldoc?Log::Log4perl">Log::Log4perl</a> for logging, wrapped with much <a href="http://search.cpan.org/perldoc?Poet::Log#CONFIGURATION">simpler configuration</a></p>
</li>
<li>
<p>Integration with <a href="http://search.cpan.org/perldoc?CHI">CHI</a> for powerful and flexible caching</p>
</li>
<li>
<p>The power of Mason for request routing and content generation</p>
</li>
<li>
<p>Easy access to common <a href="http://search.cpan.org/perldoc?Poet::Import#QUICK_VARS">objects</a> and <a href="http://search.cpan.org/perldoc?Poet::Import#UTILITIES">utilities</a> from anywhere in your application</p>
</li>
<li>
<p>The freedom to override just about any behavior with <a href="http://search.cpan.org/perldoc?Poet::Manual::Configuring">configuration</a> or <a href="http://search.cpan.org/perldoc?Poet::Manual::Subclassing">subclassing</a></p>
</li>
</ul>
<p>Poet was designed and developed over the past six years at <a href="http://www.hearst.com/magazines/hearst-digital-media.php">Hearst Digital Media</a>. Today it is used to generate Hearst&#8217;s magazine websites (including <a href="http://www.cosmopolitan.com/">Cosmopolitan</a>, <a href="http://www.esquire.com/">Esquire</a>, and <a href="http://www.goodhousekeeping.com/">Good Housekeeping</a>) as well as associated content management, subscription management and ad rotation systems. I&#8217;m very grateful to Hearst for agreeing to this open source release (though they bear no responsibility for its support or maintenance).</p>
<h3>Why another Perl web framework?</h3>
<p>To answer this requires a bit of history.</p>
<p><a href="http://search.cpan.org/perldoc?HTML::Mason">HTML::Mason</a> was one of the early Perl &#8220;web frameworks&#8221;. Like its JSP/ASP/PHP contemporaries, its main trick was embedding code in HTML, but it contained enough web-specific goodies to serve as a one-stop solution. It relied heavily on <a href="http://perl.apache.org/">mod_perl</a> and had mailing lists filled with web-related discussions having nothing to do with templating.</p>
<p>Over time, a new breed of web framework emerged &#8211; <a href="http://search.cpan.org/perldoc?Catalyst">Catalyst</a> and <a href="http://search.cpan.org/perldoc?Jifty">Jifty</a> and <a href="http://search.cpan.org/perldoc?Mojolicious">Mojolicious</a> and <a href="http://search.cpan.org/perldoc?Dancer">Dancer</a> in the Perl world, <a href="http://rubyonrails.org/">Rails</a> and <a href="http://www.sinatrarb.com/">Sinatra</a> and <a href="https://www.djangoproject.com/">Django</a> elsewhere. In these frameworks the templates moved from center stage to become just one piece of a large system.</p>
<p>HTML::Mason faced an identity dilemma; should it be a pure templating framework, or try to expand and better serve its traditional web development audience? In the end, and with coaxing from co-author Dave Rolsky, <a href="http://search.cpan.org/perldoc?Mason">Mason 2</a> shifted decisively towards the former. It shed most of its web-specific code, thanks in large part to Plack/PSGI, and became more of a generic templating system (albeit still destined to spend much of its time generating HTML).</p>
<h3>There&#8217;s two ways to use Mason</h3>
<p>So one legitimate way to use Mason is as a dedicated View component in a larger MVC framework like Catalyst or Dancer. Hence <a href="http://search.cpan.org/perldoc?Catalyst::View::Mason2">Catalyst::View::Mason2</a> and <a href="http://search.cpan.org/perldoc?Dancer::Template::Mason2">Dancer::Template::Mason2</a>. (This is how Dave prefers to roll.)</p>
<p><strong>But</strong> for me, and for some others, Mason remains a great way to handle the <em>whole</em> web request &#8211; to dispatch URLs to components and process HTTP arguments and implement common behaviors for sets of pages. I prefer my page logic right next to my page view, rather than flipping between a controller and view that are often annoyingly coupled.</p>
<p>Moreover, fifteen+ years had left me with a pile of useful ideas, techniques, and conventions for web development. Mason wasn&#8217;t the appropriate place for them any more (if it ever was) but I need to collect them somewhere.</p>
<p>This is where Poet comes in. Poet doesn&#8217;t need a controller layer; it turns web requests into Mason requests, and happily lets Mason handle the rest of the work. Poet doesn&#8217;t have Mason&#8217;s identity crisis; it is proudly web-centric, the place to put all the web-related goodness that Mason developers want nearby.</p>
<p>There&#8217;s much more to come than I could put in this initial release, and I&#8217;m looking forward to pressing on with it! I hope it makes at least a few of your lives&#8217; easier, and as always I welcome the feedback.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.openswartz.com/2012/04/21/poet-a-web-framework-for-mason/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Many CHI caches, one configuration</title>
		<link>http://www.openswartz.com/2012/03/04/configuring-many-chi-caches-in-one-place/</link>
		<comments>http://www.openswartz.com/2012/03/04/configuring-many-chi-caches-in-one-place/#comments</comments>
		<pubDate>Sun, 04 Mar 2012 22:43:28 +0000</pubDate>
		<dc:creator>Jonathan Swartz</dc:creator>
				<category><![CDATA[Mason 2]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.openswartz.com/?p=205</guid>
		<description><![CDATA[At work we have over 200 modules and Mason components that use
CHI to cache some data or HTML. Each has its own
distinct namespace to prevent collisions.
Each namespace uses one of several different storage types &#8212; memcached, local file, NFS
file &#8211; depending on its usage characteristics. Each storage type has a set of default
parameters (e.g. root_dir [...]]]></description>
			<content:encoded><![CDATA[<p>At work we have over 200 modules and Mason components that use<br />
<a href="http://search.cpan.org/perldoc?CHI">CHI</a> to cache some data or HTML. Each has its own<br />
distinct <a href="http://search.cpan.org/perldoc?CHI#namespace">namespace</a> to prevent collisions.</p>
<p>Each namespace uses one of several different storage types &#8212; memcached, local file, NFS<br />
file &#8211; depending on its usage characteristics. Each storage type has a set of default<br />
parameters (e.g. <code>root_dir</code> for file) that rarely change. Finally, there are some defaults<br />
we want to use across all of our caches.</p>
<p>To maintain a coherent cache strategy &#8212; and our sanity &#8212; we need a single place to<br />
see and adjust all this configuration.</p>
<p>So instead of repeatedly embedding parameters like this:</p>
<pre><code>my $cache = CHI-&gt;new
   (namespace =&gt; 'Foo', driver =&gt; 'File', root_dir =&gt; '/path/to/root',
    depth =&gt; 3, expires_in =&gt; '15m', expires_variance =&gt; 0.2);

...

my $cache = CHI-&gt;new
   (namespace =&gt; 'Bar', driver =&gt; 'Memcached',
    servers =&gt; [ "10.0.0.15:11211", "10.0.0.17:11211" ],
    compress_threshold =&gt; 10_000, expires_in =&gt; '1h', expires_variance =&gt; 0.2);
</code></pre>
<p>we can do this:</p>
<pre><code>my $cache = CHI-&gt;new(namespace =&gt; 'Foo');

...

my $cache = CHI-&gt;new(namespace =&gt; 'Bar');
</code></pre>
<p>then in a YAML configuration file:</p>
<pre><code>defaults:
  expires_variance: 0.2

storage:
  local_file:
    driver: File
    root_dir: /path/to/local/root
  nfs_file:
    driver: File
    root_dir: /path/to/nfs/root
  memcached:
    driver: Memcached
    servers: [ ... ]
    compress_threshold: 10_000

namespace:
  Foo: { storage: local_file, expires_in: 15m }
  Bar: { storage: memcached,  expires_in: 1h }
  Baz: { storage: memcached,  expires_in: 2h }
  ...
</code></pre>
<p>In the first paragraph we define overall defaults. In the second we define a set of<br />
storage types, each with their own defaults. In the third we assign each namespace to a<br />
storage type and an expiration time. Each level can override the defaults of previous<br />
levels, and arguments passed in <code>CHI-&gt;new</code> override anything in configuration.</p>
<p>Support for this kind of configuration is available as of CHI 0.52. You should first<br />
create a CHI subclass for your application, so as not to interfere with other CHI users in<br />
the same process:</p>
<pre><code>package My::CHI;
use base qw(CHI);
</code></pre>
<p>Then specify configuration with a hash or file:</p>
<pre><code>My::CHI-&gt;config({ storage =&gt; ..., namespace =&gt; ..., defaults =&gt; ... });

My::CHI-&gt;config(YAML::XS::LoadFile("/path/to/cache.yml"));
</code></pre>
<p>Even if you don&#8217;t have 200 namespaces, it&#8217;s nice to have a single place where you can<br />
fiddle with cache controls.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.openswartz.com/2012/03/04/configuring-many-chi-caches-in-one-place/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stop running tests on install!</title>
		<link>http://www.openswartz.com/2012/01/31/stop-running-tests-on-install/</link>
		<comments>http://www.openswartz.com/2012/01/31/stop-running-tests-on-install/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 06:51:13 +0000</pubDate>
		<dc:creator>Jonathan Swartz</dc:creator>
				<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.openswartz.com/?p=190</guid>
		<description><![CDATA[chromatic shows users how to run tests faster on cpanm and perlbrew installs. This strikes me as well-meaning advice that misses a much more basic point:
cpanm and perlbrew should not run tests by default.
This may sound heretical. Perl has always had a strong testing culture, and end-user testing may have once played a valuable role [...]]]></description>
			<content:encoded><![CDATA[<p>chromatic shows users how to <a href="http://www.modernperlbooks.com/mt/2012/01/speed-up-perlbrew-with-test-parallelism.html">run tests faster</a> on cpanm and perlbrew installs. This strikes me as well-meaning advice that misses a much more basic point:</p>
<p><em>cpanm and perlbrew should not run tests by default.</em></p>
<p>This may sound heretical. Perl has always had a strong testing culture, and end-user testing may have once played a valuable role in testing a distribution under many systems. But we now have a <a href="http://wiki.cpantesters.org/">CPAN Testers network</a> which will run tests on countless systems and Perl versions, and report failures back to the author promptly and automatically. Distributions can be sent through the Testers&#8217; gauntlet <a href="http://blogs.perl.org/users/buddy_burden/2012/01/a-tale-of-cpan-testers.html">before ever being officially released</a>. In this environment, it&#8217;s hard to see much additional value in ad hoc end-user testing.</p>
<p>As Dave Rolsky points out, we <a href="http://blog.urth.org/2009/05/the-real-problem-with-dependencies.html">install most other software without running tests</a> and rarely give it a thought.</p>
<p>None of this would matter if end-user testing was free. But it is not.</p>
<h3>The costs of end-user testing</h3>
<p><strong>Slower installs.</strong> On my system, a fresh install of <a href="http://search.cpan.org/perldoc?Moose">Moose</a> and its dependencies takes <em>three times</em> longer with tests (2 minutes versus 41 seconds). A fresh install of <a href="http://search.cpan.org/perldoc?Catalyst">Catalyst</a> and its dependencies takes nearly <em>four times</em> longer with tests (9.5 minutes versus 2.5 minutes).</p>
<p>How many new Perl users find CPAN installs much slower than they need to be? How many would choose a 3-4 times speedup if they knew it was an option? It&#8217;s like having a turbo button and leaving it unpressed by default.</p>
<p><strong>False positives.</strong> The more tests CPAN authors write, the more likely an occasional false-positive failure sneaks through (as in &#8220;Failed 1/1746 tests.&#8221;) In most such cases the module will still work for the user&#8217;s purposes. But the default behavior is to <em>prevent the module from being installed at all</em>. If your module depends on other modules, then any failure up the dependency chain likewise prevents your module from being installed, even if the failure has no bearing on your module&#8217;s efficacy.</p>
<p>How many new Perl users have unnecessarily failed to install a module like Moose or Catalyst because of an obscure, temporary failure deep in the dependency chain?</p>
<p><strong>Fear of dependencies and code reuse.</strong> Slower installs and false positives are the main reasons why people <a href="http://perlmonks.org/?node_id=760581">complain</a> about distributions having &#8220;too many dependencies&#8221;. (If the dependencies installed quickly and reliably, as they do with &#8211;notest and apt-get and yum, would anyone complain or even notice?) These  complaints in turn encourage module authors to <a href="http://perldancer.org/">reduce</a> or <a href="http://search.cpan.org/~ams/Mojolicious-2.46/lib/Mojolicious/Guides/FAQ.pod#Why_doesn%27t_Mojolicious_have_any_dependencies?">eliminate</a> their dependencies, thus reinventing where they could be reusing.</p>
<h3>It&#8217;s the wrong default for new users</h3>
<p>Some veteran Perl folks may like tests to run on every install. That&#8217;s fine. But I suspect <em>new</em> Perl users just want things to install quickly and reliably, and in any event don&#8217;t have the experience to evaluate or take action on a test failure (especially one in an obscure dependency). For these users running tests is simply the wrong default.</p>
<p>I turn on &#8211;notest on each system I administer and preach it enthusiastically to every new Perl user I encounter. But I wish I didn&#8217;t have to mention it at all.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.openswartz.com/2012/01/31/stop-running-tests-on-install/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>The inevitable Tie::CHI</title>
		<link>http://www.openswartz.com/2011/10/07/the-inevitable-tiechi/</link>
		<comments>http://www.openswartz.com/2011/10/07/the-inevitable-tiechi/#comments</comments>
		<pubDate>Fri, 07 Oct 2011 12:51:20 +0000</pubDate>
		<dc:creator>Jonathan Swartz</dc:creator>
				<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.openswartz.com/?p=183</guid>
		<description><![CDATA[Despite its lofty martial-arts name, Tie::CHI is a simple module that allows you to tie a hash to a persistent CHI cache, using any of CHI&#8217;s backends.
I hardly ever choose Tie interfaces &#8212; too much magic &#8212; but occasionally they do produce pretty code.  In this case, we have a watchdog script that sends [...]]]></description>
			<content:encoded><![CDATA[<p>Despite its lofty martial-arts name, <a href="http://search.cpan.org/perldoc?Tie::CHI">Tie::CHI</a> is a simple module that allows you to tie a hash to a persistent <a href="http://search.cpan.org/perldoc?CHI">CHI</a> cache, using any of CHI&#8217;s backends.</p>
<p>I hardly ever choose <a href="http://search.cpan.org/perldoc?perltie">Tie</a> interfaces &#8212; too much magic &#8212; but occasionally they do produce pretty code.  In this case, we have a watchdog script that sends USR2 signals to httpd processes that grow too large (so that they&#8217;ll log their call stack). Sometimes these processes stick around for a while, so I only want to send a certain number of signals per process.</p>
<pre><code>    my %kill_count;
    ...
    if ( $vsize &gt; $max_vsize ) {
        if ( $kill_count{$pid} &lt; $max_kills ) {
            kill( 'USR2', $pid );
            $kill_count{$pid}++;
            $log-&gt;warn(sprintf( "pid %d vsize %dmb &gt; %dmb, sending USR2",
                $pid, $vsize, $max_vsize ));
        }
    }
</code></pre>
<p>Then it occurred to me that the watchdog restarts frequently, so I need to keep the kill counts persistent; and I should only limit on an hourly basis, because the same pid will eventually come around again. We already have a custom CHI subclass that we use for caching all over our application, so it was easy to plug it in:</p>
<pre><code>    use Tie::CHI;
    my $cache = HM::Cache-&gt;new
       (namespace =&gt; 'watchdog/kill_count', expires_in =&gt; '1 hour');
    my %kill_count;
    tie %kill_count, 'Tie::CHI', $cache;
</code></pre>
<p>And voila, <code>%kill_count</code> is persistent, and its values decay after an hour.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.openswartz.com/2011/10/07/the-inevitable-tiechi/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A faster memory cache for CHI</title>
		<link>http://www.openswartz.com/2011/03/02/a-faster-memory-cache-for-chi/</link>
		<comments>http://www.openswartz.com/2011/03/02/a-faster-memory-cache-for-chi/#comments</comments>
		<pubDate>Wed, 02 Mar 2011 23:35:03 +0000</pubDate>
		<dc:creator>Jonathan Swartz</dc:creator>
				<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.openswartz.com/?p=178</guid>
		<description><![CDATA[I&#8217;ve released CHI 0.41 with a RawMemory driver. It&#8217;s like the regular Memory driver except that data structure references are stored directly instead of serializing / deserializing. This makes the cache faster at getting and setting complex data structures, but unlike most drivers, modifications to the original data structure will affect the data structure stored [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve released <a href="http://search.cpan.org/perldoc?CHI">CHI 0.41</a> with a <a href="http://search.cpan.org/perldoc?CHI::Driver::RawMemory">RawMemory</a> driver. It&#8217;s like the regular <a href="http://search.cpan.org/perldoc?CHI::Driver::Memory">Memory</a> driver except that data structure references are stored directly instead of serializing / deserializing. This makes the cache faster at getting and setting complex data structures, but unlike most drivers, modifications to the original data structure <em>will</em> affect the data structure stored in the cache, and vica versa. e.g.</p>
<pre><code>   my $cache = CHI-&gt;new( driver =&gt; 'Memory', global =&gt; 1 );
   my $lst = ['foo'];
   $cache-&gt;set('key' =&gt; $lst);   # serializes $lst before storing
   $cache-&gt;get('key');   # returns ['foo']
   $lst-&gt;[0] = 'bar';
   $cache-&gt;get('key');   # returns ['foo']

   my $cache = CHI-&gt;new( driver =&gt; 'RawMemory', global =&gt; 1 );
   my $lst = ['foo'];
   $cache-&gt;set('key' =&gt; $lst);   # stores $lst directly
   $cache-&gt;get('key');   # returns ['foo']
   $lst-&gt;[0] = 'bar';
   $cache-&gt;get('key');   # returns ['bar']!
</code></pre>
<p>It should work well as a short-lived <a href="http://search.cpan.org/perldoc?CHI#L1_cache">L1 cache</a> in front of memcached, for example.</p>
<p>I was motivated to create this by Yuval Kogman&#8217;s <a href="http://search.cpan.org/perldoc?Cache::Ref">Cache::Ref</a>, which is still a little faster (not having some of the overhead of CHI&#8217;s metadata and features). See the <a href="http://search.cpan.org/perldoc?CHI::Benchmarks">CHI benchmarks</a>, also new with this release.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.openswartz.com/2011/03/02/a-faster-memory-cache-for-chi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mason has routes</title>
		<link>http://www.openswartz.com/2011/02/25/mason-has-routes/</link>
		<comments>http://www.openswartz.com/2011/02/25/mason-has-routes/#comments</comments>
		<pubDate>Fri, 25 Feb 2011 04:44:05 +0000</pubDate>
		<dc:creator>Jonathan Swartz</dc:creator>
				<category><![CDATA[Mason 2]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.openswartz.com/?p=172</guid>
		<description><![CDATA[For those using Mason 2&#8217;s request dispatching features, I just released Mason::Plugin::RouterSimple, which adds basic route support courtesy of Router::Simple.
Let&#8217;s say we want to support URLs like
    /archives/2010/05

where the second and third part of the path are year and month parameters respectively.
Using the new plugin:
    %% route "{year:[0-9]{4}}/{month:[0-9]{2}}";

  [...]]]></description>
			<content:encoded><![CDATA[<p>For those using Mason 2&#8217;s <a href="http://search.cpan.org/perldoc?Mason::Manual::RequestDispatch">request dispatching</a> features, I just released <a href="http://search.cpan.org/perldoc?Mason::Plugin::RouterSimple">Mason::Plugin::RouterSimple</a>, which adds basic route support courtesy of <a href="http://search.cpan.org/perldoc?Router::Simple">Router::Simple</a>.</p>
<p>Let&#8217;s say we want to support URLs like</p>
<pre><code>    /archives/2010/05
</code></pre>
<p>where the second and third part of the path are year and month parameters respectively.</p>
<p>Using the new plugin:</p>
<pre><code>    %% route "{year:[0-9]{4}}/{month:[0-9]{2}}";

    Archives for the month of &lt;% $.month %&gt;/&lt;% $.year %&gt;:
    ...

    &lt;%init&gt;
    # Use $.month and $.year to fetch the archives
    &lt;/%init&gt;
</code></pre>
<p>The <code>route</code> command adds a route indicating how the <em>path_info</em> (the remainder of the path beyond <code>/archives</code>) should be parsed.</p>
<p>Any named captured arguments are placed in component attributes, which are declared automatically if you don&#8217;t do so manually. So above, we get auto-declared attributes <code>$.year</code> and <code>$.month</code> that are then set to &#8216;2010&#8242; and &#8216;05&#8242; for that URL.</p>
<p>You can add multiple routes and they&#8217;ll each be tried in turn. If the URL does not match any route, the component will decline, which generally results in a 404.</p>
<p>Other examples of <code>Router::Simple</code> routes:</p>
<pre><code>    route "wiki/:page";     # sets $.page
    route "download/*.*";   # sets $.splat to a 2-element arrayref
</code></pre>
<p>I chose <code>Router::Simple</code> because I liked the compact declaration syntax, but one could create similar plugins (with some shared common code) to support other routers like <a href="http://search.cpan.org/perldoc?Path::Dispatcher">Path::Dispatcher</a> and <a href="http://search.cpan.org/perldoc?Path::Router">Path::Router</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.openswartz.com/2011/02/25/mason-has-routes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing Mason 2</title>
		<link>http://www.openswartz.com/2011/02/21/announcing-mason-2/</link>
		<comments>http://www.openswartz.com/2011/02/21/announcing-mason-2/#comments</comments>
		<pubDate>Mon, 21 Feb 2011 17:19:56 +0000</pubDate>
		<dc:creator>Jonathan Swartz</dc:creator>
				<category><![CDATA[Mason 2]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.openswartz.com/?p=165</guid>
		<description><![CDATA[I&#8217;m pleased to announce Mason 2, the first major version of Mason in ten years.
For those not familiar with it, Mason is a templating framework for generating web pages and other dynamic content. Mason 2 has been rearchitected and reimplemented from the ground up, to take advantage of modern Perl techniques (Moose, Plack/PSGI) and to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m pleased to announce <a href="http://search.cpan.org/perldoc?Mason">Mason 2</a>, the first major version of Mason in ten years.</p>
<p>For those not familiar with it, Mason is a templating framework for generating web pages and other dynamic content. Mason 2 has been rearchitected and reimplemented from the ground up, to take advantage of modern Perl techniques (<a href="http://search.cpan.org/perldoc?Moose">Moose</a>, <a href="http://plackperl.org">Plack/PSGI</a>) and to correct long-standing feature and syntax inadequacies. Its new foundations should allow its performance and flexibility to far exceed Mason 1.</p>
<p>Though little original code or documentation remains, Mason&#8217;s core philosophy is intact; it should still &#8220;feel like Mason&#8221; to existing users.</p>
<p>I&#8217;ve talked about plans for Mason 2 here <a href="http://www.openswartz.com/2009/09/01/what-mason-2-0-would-look-like/">before</a>, but as things have changed in the past year and a half, here&#8217;s an updated summary:</p>
<ul>
<li>
<p><strong>Name</strong>. The name is now Mason, instead of <a href="http://search.cpan.org/perldoc?HTML::Mason">HTML::Mason</a>.</p>
</li>
<li>
<p><strong>Component classes</strong>. Each component is represented by its own (Moose) class, rather than just an instance of a common class. This means that components have their own namespaces, subroutines, methods, and attributes, and can truly inherit from one other. See <a href="http://search.cpan.org/perldoc?Mason::Manual::Components">Mason::Manual::Components</a>.</p>
</li>
<li>
<p><strong>Filters</strong>. A single powerful filter syntax and mechanism consolidates three separate filter mechanisms from Mason 1 (filter blocks, components with content, and escape flags). See <a href="http://search.cpan.org/perldoc?Mason::Manual::Filters">Mason::Manual::Filters</a>.</p>
</li>
<li>
<p><strong>Plugins</strong>. Moose roles are utilized to create a flexible plugin system that can modify nearly every aspect of Mason&#8217;s operation. Previously core features such as caching can now be implemented in plugins. See <a href="http://search.cpan.org/perldoc?Mason::Manual::Plugins">Mason::Manual::Plugins</a>.</p>
</li>
<li>
<p><strong>Web integration</strong>. Mason 1&#8217;s bulky custom web handling code (<code>ApacheHandler</code>, <code>CGIHandler</code>) has been replaced with a simple <a href="http://search.cpan.org/perldoc?Mason::Plugin::PSGIHandler">PSGI handler</a> and with plugins for web frameworks like <a href="http://search.cpan.org/perldoc?Catalyst::View::Mason2">Catalyst</a> and <a href="http://search.cpan.org/perldoc?Dancer::Template::Mason2">Dancer</a>. The core Mason distribution is now completely web-agnostic. See <a href="http://search.cpan.org/perldoc?Mason::Plugin::PSGIHandler">Mason::Plugin::PSGIHandler</a>.</p>
</li>
<li>
<p><strong>File naming</strong>. Mason now facilitates and enforces (in a customizable way) standard file extensions for components: .m (top-level components), .mi (internal components), and .pm (pure-perl components).</p>
</li>
</ul>
<p>See <a href="http://search.cpan.org/perldoc?Mason::Manual::UpgradingFromMason1">Mason::Manual::UpgradingFromMason1</a> for a more detailed list of changes.</p>
<p>Mason 2 is obviously still in alpha status, but it has a fair sized test suite and I&#8217;m eager to start building web projects with it. I hope you&#8217;ll give it a try too! Post feedback here or on the <a href="https://lists.sourceforge.net/lists/listinfo/mason-users">Mason user&#8217;s list</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.openswartz.com/2011/02/21/announcing-mason-2/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Getting plugin-happy</title>
		<link>http://www.openswartz.com/2011/01/14/getting-plugin-happy/</link>
		<comments>http://www.openswartz.com/2011/01/14/getting-plugin-happy/#comments</comments>
		<pubDate>Fri, 14 Jan 2011 22:46:29 +0000</pubDate>
		<dc:creator>Jonathan Swartz</dc:creator>
				<category><![CDATA[Mason 2]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.openswartz.com/?p=161</guid>
		<description><![CDATA[After converting Mason 2 to use Dist::Zilla and Pod::Weaver, I am starting to think in plugins and see opportunities for them everywhere.
As just one example, I initially added a cache feature to Mason 2, just because it was there in Mason 1 and seemed generally useful. But now I realize it can be cleanly separated [...]]]></description>
			<content:encoded><![CDATA[<p>After converting Mason 2 to use <a href="http://search.cpan.org/perldoc?Dist::Zilla">Dist::Zilla</a> and <a href="http://search.cpan.org/perldoc?Pod::Weaver">Pod::Weaver</a>, I am starting to think in plugins and see opportunities for them everywhere.</p>
<p>As just one example, I initially added a <em>cache</em> feature to Mason 2, just because it was there in Mason 1 and seemed generally useful. But now I realize it can be cleanly separated into <a href="https://github.com/jonswar/perl-mason/tree/master/lib/Mason/Plugin/Cache">its own plugin</a>.</p>
<p>There&#8217;s no real performance or footprint advantage for those that omit the plugin.  What it <strong>does</strong> do is put all the cache related code, documentation, and tests in a single place. As small as it is, the cache feature touched many of the main Mason modules in some way; now it is all in its own directory. It also makes me more amenable to expanding the feature (e.g. with new parameters or methods), because I&#8217;m not worried about disproportionately &#8220;polluting&#8221; the main code and API.</p>
<p>Of course, deciding what is a plugin versus a built-in feature (plus that third category, a plugin-in-name that really everyone expects to install) is the age-old question.  Too many plugins will of course hurt performance, because each one adds a layer of method modifiers, and will also hurt useability and readability. I&#8217;m still quite confused about where and how Dist::Zilla performs many of its tasks, and part of that is the sheer number of plugins one needs for a typical installation. It&#8217;s a virtual certainty that in my new enthusiasm I&#8217;ll over-plugin somewhere.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.openswartz.com/2011/01/14/getting-plugin-happy/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mason 2: Filters</title>
		<link>http://www.openswartz.com/2010/12/27/mason-2-filters/</link>
		<comments>http://www.openswartz.com/2010/12/27/mason-2-filters/#comments</comments>
		<pubDate>Mon, 27 Dec 2010 10:47:46 +0000</pubDate>
		<dc:creator>Jonathan Swartz</dc:creator>
				<category><![CDATA[Mason 2]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.openswartz.com/?p=155</guid>
		<description><![CDATA[In Mason 1 there are several ways to filter content: the &#60;%filter&#62; section, escape flags, and Component Calls with Content. Each of these has their own disparate implementation and API.
In Mason 2 we aim to unify these with a single implementation and a more consistent syntax.
A set of standard filters are automatically available in components, [...]]]></description>
			<content:encoded><![CDATA[<p>In Mason 1 there are several ways to <em>filter</em> content: the <a href="http://www.masonhq.com/docs/manual/Devel.html#__filter__section">&lt;%filter&gt;</a> section, <a href="http://www.masonhq.com/docs/manual/Devel.html#escaping_expressions">escape flags</a>, and <a href="http://www.masonhq.com/docs/manual/Devel.html#component_calls_with_content">Component Calls with Content</a>. Each of these has their own disparate implementation and API.</p>
<p>In Mason 2 we aim to unify these with a single implementation and a more consistent syntax.</p>
<p>A set of <a href="https://github.com/jonswar/perl-mason/blob/master/lib/Mason/Filters/Standard.pm">standard filters</a> are automatically available in components, and other filter packages can be loaded via <a href="http://www.openswartz.com/2010/12/14/mason-2-plugins/">plugins</a>.</p>
<h3><a name="block_invocation">Invoking filters (block syntax)</a></h3>
<p>Here&#8217;s the typical way of invoking a filter:</p>
<pre>
&lt;% $.Trim { %&gt;
This string will be trimmed
&lt;/%&gt;
</pre>
<p>Things to note here:</p>
<ul>
<li>An <code>{</code> at the end of a <code>&lt;% %&gt;</code> tag denotes a filter call.</li>
<li>The <code>&lt;/%&gt;</code> tag marks the end of the filtered content.</li>
<li>The expression <code>$.Trim</code>, aka <code>$self-&gt;Trim</code>, is a method call on the component object which returns a filter. In general everything before the brace is evaluated and is expected to return a filter or list of filters.</li>
<li>Filter names use <a href="http://c2.com/cgi/wiki?CamelCase">CamelCase</a> to distinguish themselves from other methods in the <code>Mason::Component</code> namespace. Another option was to use a standard prefix or suffix, e.g. <code>trim_filter</code> or <code>filter_trim</code>, but I thought this was the least ugly option and made filters look a little more like built-in tags.</li>
</ul>
<p>Filters can take arguments:</p>
<pre>
&lt;% $.Repeat(3) { %&gt;
  There's no place like home.
&lt;/%&gt;

  ==&gt;  There's no place like home.
 There's no place like home.
 There's no place like home.
</pre>
<p>Again, the expression <code>$.Repeat(3)</code> returns a filter, meaning that it can<br />
be curried:</p>
<pre>
% my $repeat_three = $.Repeat(3);
&lt;% $repeat_three { %&gt;
  There's no place like home.
&lt;/%&gt;
</pre>
<p>A simple filter is just a subroutine that takes text as input and return the<br />
new text. Thus you can create one-off filters with anonymous subroutines:</p>
<pre>
&lt;% sub { reverse($_[0]) } { %&gt;Hello&lt;/%&gt;

     ==&gt; olleH
</pre>
<p>Filters can be nested, with separate tags:</p>
<pre>
&lt;% $.Trim { %&gt;
  &lt;% sub { uc($_[0]) } { %&gt;
    This string will be trimmed and uppercased
  &lt;/%&gt;
&lt;/%&gt;
</pre>
<p>or within a single tag:</p>
<pre>
&lt;% $.Trim, sub { uc($_[0]) } { %&gt;
  This will be trimmed and uppercased
&lt;/%&gt;
</pre>
<p>Multiple filters within the same tag are applied, intuitively, in reverse order with the last one being innermost. e.g. in this block</p>
<pre>
% my $i = 1;
&lt;% $.Repeat(3), $.Cache($key, '1 hour') { %&gt; &lt;% $i++ %&gt; &lt;/%&gt;

  =&gt; 1 1 1
</pre>
<p>the output of <code>&lt;% $i++ %&gt;</code> is cached, and then repeated three times, whereas in this block</p>
<pre>
% my $i = 1;
&lt;% $.Cache($key, '1 hour'), $.Repeat(3) { %&gt; &lt;% $i++ %&gt; &lt;/%&gt;

  =&gt; 1 2 3
</pre>
<p><code>&lt;% $i++ %&gt;</code> is executed and output three times, and then the whole thing cached.</p>
<h4>Invoking filters (pipe syntax)</h4>
<p>Filters can also appear in a limited way inside a regular <code>&lt;% %&gt;</code> tag; this replaces Mason 1&#8217;s escape flags.</p>
<pre>
&lt;% $content | NoBlankLines,Trim %&gt;
</pre>
<p>The filter list contains one or more comma-separated names, which are treated as methods on the current component class. With this syntax you cannot use anonymous subroutines or variables as filters, or pass arguments to filters (but you can define local filter methods to get around this).</p>
<p>One common use of this form is to escape HTML strings:</p>
<pre>
&lt;% $message_body | H %&gt;
</pre>
<p>The <code>H</code> filter is provided along with other web-related filters in <a href="https://github.com/jonswar/perl-mason/blob/master/lib/Mason/Plugin/HTMLFilters.pm">Mason::Plugin::HTMLFilters</a>.</p>
<h4>Applying filter to current component</h4>
<p>Mason 1&#8217;s <a href="http://www.masonhq.com/docs/manual/Devel.html#__filter__section">&lt;%filter&gt;</a> section was good for filtering the content of the current component. e.g. to make it uppercase:</p>
<pre>
&lt;%filter&gt;
$_ = uc($_);
&lt;/%filter&gt;
</pre>
<p>In Mason 2 the most succinct replacement is currently an <code>around</code> modifier:</p>
<pre>
&lt;%around main&gt;
&lt;% sub { uc($_[0]) } { %&gt;
% $self-&gt;$orig();
&lt;/%&gt;
&lt;/%around&gt;
</pre>
<h4>Creating filters</h4>
<p>Here&#8217;s a filter package that implements two filters, <code>Upper</code> and <code>Lower</code>:</p>
<pre>
package MyApp::Filters;
use Method::Signatures::Simple;
use Moose::Role;

method Upper () {
    return sub { uc($_[0]) }
}

method Lower () {
    return sub { lc($_[0]) }
}

1;
</pre>
<p>To use these in a component:</p>
<pre>
&lt;%class&gt;
with 'MyApp::Filters';
&lt;/%class&gt;

&lt;% $.Upper { %&gt;
...
&lt;/%&gt;
</pre>
<p>Or if you want them available to all components, put them in <code>Base.pm</code> at the top of your component hierarchy, or in your application&#8217;s <code>Mason::Component</code> subclass.</p>
<h4>Simple vs. dynamic filters</h4>
<p>A <em>simple filter</em> is a code ref which takes a string and returns the output, like <code>Upper</code> and <code>Lower</code> above.</p>
<p>A <em>dynamic filter</em> (a <code>Mason::DynamicFilter</code> object) contains a code ref which takes a <em>yield block</em> and returns the output. A yield block is a zero-argument code ref that returns a content string.</p>
<p>The power of dynamic filters is that they can choose if and when to execute the yield block. For example, here&#8217;s the standard <code>Cache</code> filter in action:</p>
<pre>
&lt;% $.Cache($key, '1 hour') { %&gt;
... some computed content ...
&lt;/%&gt;
</pre>
<p>This caches the inner content for one hour based on cache key <code>$key</code>. Here&#8217;s the implementation:</p>
<pre>
method Cache ( $key, $set_options ) {
    Mason::DynamicFilter-&gt;new(
        filter =&gt; sub {
            my $yield = shift;
            $self-&gt;cmeta-&gt;cache-&gt;compute( $key, $yield, $set_options );
        }
    );
}
</pre>
<p>Using CHI&#8217;s <a href="http://search.cpan.org/perldoc?CHI#Getting_and_setting">compute</a> method, we check the cache first and return the output immediately if it is available. Only on a cache miss do we actually execute the (presumably expensive) yield block. This could not be implemented with a simple filter since the content would be computed every time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.openswartz.com/2010/12/27/mason-2-filters/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

