I started
thinking about replacing Typo
back in October of 2006, and my home-brew project to do so is at the
point where it's usable as a replacement. In fact, I cut over this
morning, so you're looking at it right now.
The current implementation represents an investment of around 60
hours of learning and hacking time spent on Apache, FastCGI, Atom,
XHTML, and Haskell.
Why Not X?
It is reasonable to ask "Why not use X?" where reasonable
values for X include default blogging tools like Wordpress or Roller, a more recent
version of Typo, some language other than Haskell (like Erlang or
OCaml or Scala), or an existing Haskell framework like HApps or Hope. The short answer is
that I rolled my own because I wanted to roll my own.
Tooling and Methodology
I used the default tooling stack of Emacs (the Aquamacs flavor) with haskell-mode, GHC, and Darcs for revision control. My workflow
loop was equivalently simple: I worked in Emacs until I thought that
something might work and then loaded a module into ghci
to experiment with.
Basic Architecture
The basic architecture is straightforward; here are the highlights:
- Container: FastCGI handler implemented in Haskell that
parses request URIs to determine how to respond. Apache with
mod_fastcgi is configured as described in an earlier post.
- Storage: Plain text, simple file storage of entities (posts, comments,
drafts, etc.) in a human editable, human readable format.
- Concurrency: An event loop that listens on a Haskell
Chan
and manages a single in-memory instance of the data. The event loop
runs on a lightweight background thread that gets forked when Apache
spins-up the FastCGI handler, and the approach is equivalent to the
one I used for the sequence
number generator experiment.
- Browser Views: XHTML rendering via the
Text.XHtml
combinator package.
- Atom Feeds: A modified version of the lightweight Atom library that I posted
on previously.
Early Returns and Open Items
My expectations are met so far. The implementation is deployed on
my virtual server at Linode. Some
ad hoc benchmarking shows that it will support sustained 50 req/sec
loads with 10 or 20 concurrent clients without issue, and that's a
stark contrast to Typo's performance of four requests per second
(downhill and with the wind). (Benchmarking traffic may well be
saturating the network between here and there, so it might even do a
bit more.) Turning on profiling
shows that most of the time is taken in string concatenation for a
page view or a feed. One option would be to set up conditional
GET and some basic caching, and switching to Data.ByteString
would be another.
There are two open items I'm still thinking about: dynamic content
in the browser and comments.
For dynamic content in the browser, i.e., integration via
Javascript clients to HTTP APIs, I experimented a bit with in-page
widgets that do a bit of DOM rewriting to display fancy badges from del.icio.us or Reddit or shared items from
Google Reader, but pages load more slowly, it requires clients to have
Javascript enabled, and it's incompatible
with XHTML. (The one compromise for the moment is the Flickr montage, since it adds a
splash of color.) Instead, I'm planning to add additional background
threads to the application to poll del.icio.us, Flickr, and other
services via HTTP APIs and then vend cached data to sidebar widgets.
The second item is support for comments, trackbacks, referrers, and
the like, and that's just a matter of me deciding how I want to manage
the workflow and ensure a good experience for repeat commenters or
correspondents (i.e., people who link here).
Open Source?
I will make source code available as a Darcs repository at some point in the near
future, but it's not a priority for me. The milestone I'd like to
achieve before releasing the source is to have the cabal builds all squeaky
clean, and that's not far off. (Right now, things are just built with
ghc --make.) Even then, I still wouldn't call it "open
source". Calling something "open source", to me, should carry with it
an implicit promise of usefulness and fitness for purpose, but
as the name might suggest, I intend this to be a personal
publishing platform.