My current Perl Ironman Challenge status is: My Ironman Badge

Friday, April 9, 2010

Rewriting POE::Component::Server::PSGI

So in following up with last post about TraitFor::Controller::Ping, I've been working on a monitoring framework and daemon. But today's post isn't about that, but about one of the sub components of that project, mainly the embedded HTTP server.

I discussed last that I wanted to make POE::Component::Server::PSGI a bit more resource conservative and basically pair it down from the POE::Component::Server::TCP it was using (which creates a new session for each socket connection), down to its constituent parts, mainly SocketFactory, and manage the ReadWrite creation myself. In my monitoring framework I want to display results via a little Web::Simple magic, but I want the app.psgi to take advantage of the frameworks tools to connect to the database and make use of the Schema class. I also wanted to save all of the work from having to open yet another database connection just for the web app. So how do I pass those structures along so the web app can use them?

It turns out that POE::Component::Server::PSGI doesn't really provide any means in which to hook into the process to provide any customizations. This is bad if you want to provide an application specific micro-framework to your web app. So I had no choice but to start working on a fork: POEx::Role::PSGIServer

First step in the process was to basically start over, but reference frodwith's logic as much as possible. To that end, I started with modern POE tools, mainly, POEx::Role::TCPServer which does exactly what I describe above: a single session managing a collection of wheels (including SocketFactory).

The PSGI specification also provides a mechanism for streaming content via a filehandle. And to support that mechanism, I wrote POEx::Role::Streaming, which will take as arguments, two file handles and stream from one to the other. This encapsulates the typical pattern of streaming and since it is a role, it is easy to consume and override with implementation specific details (which is required to support chunked transfer encoding).

Then there needed to be a lot more validation of parameters. So POEx::Types::PSGIServer was written to do some light validating on the various data structures passed around inside the role.

Lastly, I needed to split out as many of the closures as possible into real live methods so that I could either advise them or override them. Not only that, but also break up the larger pieces of code into smaller bite sized chunks to allow for maximum customization (ie, what to pass when converting the HTTP::Request into PSGI $env hash).

All of this is a net win. I am not quite finished yet, but you can take a look at what I have so far at at github: poex-role-psgiserver. Docs and tests will be written next. I'll probably cargo-cult frodwith's tests as much as possible to save some time. Expect a release very very soon.

Anyhow, a BIG thanks to frodwith for his work on POE::Component::Server::PSGI. Next time you see him, buy him an alcoholic beverage of your choice. I know I will.

No comments:

Post a Comment