<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Napkins</title>
	<atom:link href="http://napkins.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://napkins.wordpress.com</link>
	<description>Keeping it clean</description>
	<lastBuildDate>Fri, 11 Feb 2011 01:05:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='napkins.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Napkins</title>
		<link>http://napkins.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://napkins.wordpress.com/osd.xml" title="Napkins" />
	<atom:link rel='hub' href='http://napkins.wordpress.com/?pushpress=hub'/>
		<item>
		<title>ZDStack&#8217;s New Storage Engine</title>
		<link>http://napkins.wordpress.com/2009/03/16/zdstacks-new-storage-engine/</link>
		<comments>http://napkins.wordpress.com/2009/03/16/zdstacks-new-storage-engine/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 00:31:27 +0000</pubDate>
		<dc:creator>Charlie</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[ZDStack]]></category>

		<guid isPermaLink="false">http://napkins.wordpress.com/2009/03/16/zdstacks-new-storage-engine/</guid>
		<description><![CDATA[And it&#8217;s no surprise, I chose SQLAlchemy. My reasoning in this was 2 fold: It would be really nice if I could keep the database &#38; webserver off the game server If you don&#8217;t want to run a database &#38; webserver on your game server, you&#8217;re basically looking at Tokyo Tyrant, MySQL, or PostgreSQL&#8230; and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=148&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>
And it&#8217;s no surprise, I chose SQLAlchemy.  My reasoning in this was 2 fold:
</p>
<h2>It would be really nice if I could keep the database &amp; webserver off the game server</h2>
<p>
If you don&#8217;t want to run a database &amp; webserver on your game server, you&#8217;re basically looking at Tokyo Tyrant, MySQL, or PostgreSQL&#8230; and I guess you can throw CouchDB in there for ultimate confusion.  However, the only one out of those four that I would want running on the same machine (if I didn&#8217;t have multiple servers but I still wanted stats) is Tokyo Tyrant, er, Tokyo Cabinet.
</p>
<h2>I don&#8217;t think key=&gt;value storage is going to work.</h2>
<p>
At the end of it though, I really don&#8217;t think a key=&gt;value setup will work for ZDStack, I mean, for the Player=&gt;IP lookup it would, but if we&#8217;re storing all stats like Frags/Deaths, Flag Touches &amp; Flag Returns, I think we&#8217;re going to have to go relational.  And the only reasonable way to use a network-accessible RDBMS as well as a low-overhead RDBMS is to use SQLite locally and MySQL/PostgreSQL remotely; and the only reasonable way to do that in Python is SQLAlchemy.
</p>
<h2>What does this mean for IDL?</h2>
<p>
Honestly I don&#8217;t know.  I mean right now nothing is imperative; ZDStack could be fully ported to SQLAlchemy and we could keep the current system of log uploading as-is in IDL.  That&#8217;s the nice part.  But the <b>COOL AS SHIT OMFG</b> part is that I could port the IDL site to not-Django and simply mark games as &#8220;Official IDL Games&#8221; for their stats to be counted.  The thought had crossed my mind that I could use the Django ORM instead of SQLAlchemy (for ZDStack), but I think that the IDL site&#8217;s additional needs in terms of Players, Teams, Seasons, etc. complicate the setup too much for my brain, and would be work enough that the additional work needed to port to a different framework is relatively insignificant.
</p>
<h2>When will you ever get this done?</h2>
<p>Ha ha ha ha ha.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/napkins.wordpress.com/148/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/napkins.wordpress.com/148/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/napkins.wordpress.com/148/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/napkins.wordpress.com/148/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/napkins.wordpress.com/148/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/napkins.wordpress.com/148/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/napkins.wordpress.com/148/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/napkins.wordpress.com/148/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/napkins.wordpress.com/148/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/napkins.wordpress.com/148/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/napkins.wordpress.com/148/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/napkins.wordpress.com/148/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/napkins.wordpress.com/148/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/napkins.wordpress.com/148/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=148&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://napkins.wordpress.com/2009/03/16/zdstacks-new-storage-engine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a75b9492708c1ace8853340fe70c6c18?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Charlie</media:title>
		</media:content>
	</item>
		<item>
		<title>Considering ZDStack 0.11</title>
		<link>http://napkins.wordpress.com/2009/03/16/considering-zdstack-011/</link>
		<comments>http://napkins.wordpress.com/2009/03/16/considering-zdstack-011/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 22:54:50 +0000</pubDate>
		<dc:creator>Charlie</dc:creator>
				<category><![CDATA[IDL]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[ZDaemon]]></category>
		<category><![CDATA[ZDStack]]></category>

		<guid isPermaLink="false">http://napkins.wordpress.com/2009/03/16/considering-zdstack-011/</guid>
		<description><![CDATA[Well I&#8217;ve been thinking a lot about ZDStack lately, and there&#8217;s some big changes I want to make. Remove logfile dependency. zserv actually prints its general log to STDOUT, so having it save a general log to disk is entirely redundant. I figured this out while working on 0.9, but since there&#8217;s not a direct [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=146&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Well I&#8217;ve been thinking a lot about ZDStack lately, and there&#8217;s some big changes I want to make.</p>
<h2>Remove logfile dependency.</h2>
<p>zserv actually prints its general log to STDOUT, so having it save a general log to disk is entirely redundant.  I figured this out while working on 0.9, but since there&#8217;s not a direct correllation between player names and their IP addresses/ports, I figured we would have to use the connection log anyway&#8230; and since we&#8217;re doing that we may as well use the general log and send STDOUT to /dev/null.  Well now ZDStack doesn&#8217;t use the connection log for anything, instead relying on the &#8216;players&#8217; command.  So there&#8217;s really two steps in this:</p>
<ol>
<li>Move ZDStack over to using zserv&#8217;s STDOUT for event handling.</li>
<li>Make log generation configurable in the config file.</li>
</ol>
<h2>Add timestamps to log events.</h2>
<p>Should a user decide they want logs, I won&#8217;t simply turn zserv&#8217;s general log on.  I will add timestamping to all lines.  Newer versions of zserv add timestamps to the lines so they won&#8217;t need them added.  I&#8217;m a little fuzzy on the implementation details of this still, but it&#8217;s looking more and more like we&#8217;re heading towards time-based stats for IDL, and timestamps are required for that.</p>
<h2>Really truly and honestly make enabling/disabling features work.</h2>
<p>For a number of features, attempting to enable or disable them doesn&#8217;t have any appreciable effect.  Player =&gt; IP logging is disabled in 0.10, and stats are always collected (for plugins, etc.) whether they&#8217;re disabled or not.  Stats is just my laziness, pushing all the logic changes required for the case where stats are disabled is a lot of work and at the time it didn&#8217;t seem worth it to me.  Player =&gt; IP logging is just dependent upon a change that&#8217;s too big for 0.10.</p>
<h2>Find a proper storage engine.</h2>
<p>A couple years ago <a href="http://pyxse.googlecode.com">PyXSE</a> was my baby.  I actually wrote a BitTorrent service using it as a storage backend (<a href="http://torrentnest.googlecode.com">TorrentNest!</a>).  But it is extremely CPU heavy, and not having looked at the code in years it would probably be more difficult for me to get back into it than it is to just choose a different solution.</p>
<p>Specifically I&#8217;m between Tokyo Cabinet &amp; SQLite.  Both seem to offer pretty great performance and simple APIs, but that&#8217;s not really what&#8217;s making this decision hard.  It&#8217;s more me being torn between what belongs in ZDStack and what belongs in ZDWebStack, and after some thinking I sort of have a vague idea of how I want to do things.  For instance, it is dumb that ZDWebStack has to bother the ZDStack process whenever it wants anything.  It basically means that ZDStack has multiple responsibilities and it really clutters the code up.  What I think I should do is have ZDStack just for process management, event handling and plugins, and pull all the &#8220;stats&#8221; stuff into separate modules.  ZDStack&#8217;s RPC interface really ought to just be for process and current game information.  Old stuff should be stored somewhere and served up via ZDWebStack (or some HTTP-accessible layer).</p>
<p>Which, sadly, will change the RPC API again.  Sigh.  Maintaining the wiki for that is a pain in the ass by itself.</p>
<p>Anyway here&#8217;s the pros of choosing SQLite:</p>
<ul>
<li>Support is included in Python 2.5 and beyond.</li>
<li>Compiling SQLite itself is very simple.</li>
<li>It uses a standard SQL/DB-API2 interface, which will make IDL site integration easier.</li>
</ul>
<p>And pros of choosing Tokyo Cabinet:</p>
<ul>
<li>Nice, simple key=&gt;value storage.</li>
<li>Management process included!</li>
</ul>
<p>Honestly after I think about it for a while, I don&#8217;t like the idea of having 3 daemons for ZDStack (1 ZDStack, 1 storage engine daemon and 1 ZDWebStack).  I would rather have just the 2 daemons, and a common library for handling access to the storage engine.  Then again that doesn&#8217;t exclude Tokyo Cabinet, and its management process is still a feature.  For instance, the plan for TotalTrash is to have ZDStack on the Chicago server, and have ZDWebStack on TotalTrash itself (the VPS), to really minimize lag.  Some kind of HTTP-accessible layer is required to maintain that sort of setup, and not having to write one is a big plus.  On the other hand I don&#8217;t think I&#8217;m that wild about the API, but it looks easy enough to wrap.</p>
<p>As a side note, Tokyo Cabinet is badass&#8230; if only for its changing title on the front page.  Look what I got while wildly refreshing the Japanese page:</p>
<p>東京収納棚: あんなの飾りです！偉い人にはそれが分からんのですよ！<br />
Translated by Google Translate: &#8220;Tokyo rack: A pretty-like! I&#8217;m a big man that beats me!&#8221;<br />
東京収納棚: 見える！私にもレコードが見える！<br />
Translated by Google Translate: &#8220;Tokyo rack: visible! Record is visible to me!&#8221;<br />
ROFL.</p>
<p>Anyway, breaking things out like this would really improve the clarity of ZDStack&#8217;s code.  Hopefully I get time to do all this!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/napkins.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/napkins.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/napkins.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/napkins.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/napkins.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/napkins.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/napkins.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/napkins.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/napkins.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/napkins.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/napkins.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/napkins.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/napkins.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/napkins.wordpress.com/146/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=146&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://napkins.wordpress.com/2009/03/16/considering-zdstack-011/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a75b9492708c1ace8853340fe70c6c18?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Charlie</media:title>
		</media:content>
	</item>
		<item>
		<title>What Is Up In Web Development</title>
		<link>http://napkins.wordpress.com/2009/03/16/what-is-up-in-web-development/</link>
		<comments>http://napkins.wordpress.com/2009/03/16/what-is-up-in-web-development/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 21:09:25 +0000</pubDate>
		<dc:creator>Charlie</dc:creator>
				<category><![CDATA[General Commentary]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://napkins.wordpress.com/2009/03/16/what-is-up-in-web-development/</guid>
		<description><![CDATA[I&#8217;m still trying to wrap my head around the crazy stuff happening in the webdev space, so this post is more &#8220;thinking aloud&#8221; than anything else. Thanks for indulging. So programming for the web is hard. Your challenges end up being: HTTP is stateless, so you have to add a state layer. Repeating (X)HTML sucks [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=138&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>
I&#8217;m still trying to wrap my head around the crazy stuff happening in the webdev space, so this post is more &#8220;thinking aloud&#8221; than anything else.  Thanks for indulging.
</p>
<p>
So programming for the web is hard.  Your challenges end up being:</p>
<ol>
<li>HTTP is stateless, so you have to add a state layer.</li>
<li>Repeating (X)HTML sucks hard.</li>
<li>Some of the people who work on your site may not be programmers.</li>
</ol>
<p>
Of course, solving these problems is easy&#8230; until you start to think about performance.  Doing so adds the following challenges:</p>
<ol>
<li>
            Most of the time, you should consider the possibility of handling a ridiculous amount of requests/second, each of which hits your state layer something like 1000 times.
        </li>
<li>
            Connecting to/Loading your state layer for every request is VERY slow.
        </li>
<li>
            Loading some kind of templating engine for every request is VERY slow.
        </li>
</ol>
<p>
And these are just the basic architecture challenges.  We&#8217;re not even talking about:</p>
<ul>
<li>Coding for all browsers.</li>
<li>Coding for accessibility.</li>
<li>Site design (look &amp; feel, navigation, etc.)</li>
</ul>
<p>&#8230;and we won&#8217;t, because I&#8217;m no good at that stuff.  Anyhow, let&#8217;s look at contemporary solutions to the above problems.</p>
<h2>HTTP is stateless, so you have to add a state layer.</h2>
<h3>RDBMS!</h3>
<p>
Obviously the most common choice for state is an RDBMS.  They solve so many problems it&#8217;s really tough to justify using anything else:</p>
<ul>
<li>Easy concurrency.</li>
<li>Easy scalability.</li>
<li>Easy redundancy.</li>
<li>Language-neutral (sorta, it all uses SQL at some point).</li>
<li>Network-accessible.</li>
</ul>
<p>
Of course, anyone who&#8217;s worked with an RDBMS on a large scale (like millions of rows involving joins &amp; indexing) is desperately looking for something to stop the relentless headaches:</p>
<ul>
<li>Schema changes are almost impossible (&#8220;schemas&#8221; suck anyway).</li>
<li>You are using a lot of disk space for what seems like no reason.</li>
<li>Performance goes way, way down&#8230; so you throw machines at it.</li>
</ul>
<p>
Really, an RDBMS really goes against the idea of Web 2.0&#8230; which, because they were so integral to the Web 2.0 revolution to begin with, is hard to swallow.  But at some point, you will realize that RDBMSs are the antithesis of agile, flexible programming.
</p>
<p>
Additionally they really cloud your conception of your site layout.  For most sites, I&#8217;d wager that it doesn&#8217;t make any sense to map your URLs to your database tables&#8230; well excluding things like administrative front-ends.  But since it&#8217;s so easy to just map form fields to DB columns, and it&#8217;s so easy to map HTTP operations to DB operations, it&#8217;s really hard to tell your logical brain that these pieces actually shouldn&#8217;t go together&#8230; at least not in terms of your main site.
</p>
<h3>Something Else!</h3>
<p>
The sad fact is that there are few alternatives to using an RDBMS.  Right off the bat, you&#8217;re giving away tons of great advantages:</p>
<ul>
<li>A whole Internet&#8217;s worth of documentation &amp; experience.</li>
<li>Bug fixes.</li>
<li>Tested language interfaces.</li>
<li>Tested language abstraction layers.</li>
</ul>
<p>If you start looking for alternatives, you soon start to feel that, on one hand, the Internet hates RDBMSs&#8230; but on the other hand views using anything else as CRAZY RADICAL and TOTALLY RISKY WHOA!  Face it, RDBMSs have been around for decades.  Technologies and concepts trying to replace them (legitimately) haven&#8217;t even been around for more than a few years.
</p>
<p>
If you decide you&#8217;re brave, you have a few options:</p>
<ul>
<li>CouchDB</li>
<li>SQLite (kind of an RDBMS, but kind of not)</li>
<li>Tokyo Cabinet</li>
<li>
            Something you create yourself, even if you use CouchDB/SQLite/Tokyo Cabinet somewhere along the way.
        </li>
</ul>
<p>
Not having gone this route myself, it&#8217;s hard for me to say whether this works out or not.  I can imagine sinking a lot of time, thought and code into this scheme, but I&#8217;ve done that with RDBMSs too&#8230; so that may or may not be a con.  I also have to wonder about the scalability options with any of these solutions.  RDBMSs are designed to scale, even if their scaling method is a hellish punishment you wouldn&#8217;t even wish on your worst enemies.  These say they&#8217;re designed with scalability in mind, but I can&#8217;t get over my initial mistrust of technologies so new.  Then again, it seems insane to trust my unfoundable mistrust over the word of a guy much smarter than me who developed the software.
</p>
<h2>Repeating (X)HTML sucks hard.</h2>
<p>
    The main solutions to this problem are:</p>
<ul>
<li>Use some kind of templating language.</li>
<li>
            Auto-generate (X)HTML, the generation of which will be controlled by&#8230; some kind of templating language.
        </li>
</ul>
<p>
Love it or hate it, (X)HTML is here with us now, and aside from doing something crazy proprietary or something that works in exactly 1 browser, you&#8217;re stuck with it.  Much of the sadness can be alleviated with the use of a templating language, but none of these templating languages are as fast as static (X)HTML, and they, of course, are additional pieces of software with the inherent bugs and learning curve.  Probably the biggest benefit of templating languages is their ability to shrink the raw size of sites on disk&#8230; at first anyway.  Oftentimes you&#8217;ll build a huge webapp out of your templates before you realize what horror you&#8217;ve wrought.
</p>
<h2>Some of the people who work on your site may not be programmers.</h2>
<p>
I don&#8217;t even know if this is a problem.  At the risk of sounding bigoted: DON&#8217;T BE AN IDIOT.  I mean it&#8217;s not even the hard part of programming, we&#8217;re talking learning a templating language.  Even if that language is PHP, your backend guys should have things abstracted to the point where your code is very, very obvious and simple.  And if you can&#8217;t wrap your head around Javascript, you&#8217;re either a very high-level designer (which I have total respect for because I am quite horrible at it), or you&#8217;re worthless.  Sorry.
</p>
<h2>Wow is this site so slow I am just gonna die right now.</h2>
<p>
Well after you&#8217;ve added a bunch of stuff to the HTTP protocol to make it suitable for applications, you realize that you&#8217;ve cut your requests/second 1000x.  Holy crap!  Why OH GOD WHY IS THIS?!?!  Well a few reasons:</p>
<ul>
<li>Your template software is being loaded for every request.</li>
<li>Your interface to your state layer is loaded for every request.</li>
<li>
            Your application is requesting data from your state layer for every request.
        </li>
</ul>
<p>Fortunately there are a number of ways to fix these problems, or at least mitigate their crappiness, but they all come down to holding a bunch of stuff in RAM, which is the fastest place to hold things you don&#8217;t want to have to re-create all the time.</p>
<h3>Caching</h3>
<p>
Probably the first thing anyone with enough RAM should consider is memcached.  Unless your site is incredibly dynamic (most sites are less dynamic than their authors think they are), memcached will save the day.
</p>
<h3>FastCGI (etc.)</h3>
<p>
You run a separate, daemon process (actually you usually run more than one unless you&#8217;re a madman using threading) that creates database connections, parses templates, controls what output to produce based upon its URL, and so on.
</p>
<h3>mod_*</h3>
<p>
You add support for the language your state layer and template parser are written in to your HTTP server.
</p>
<h3>Application Servers</h3>
<p>
This is much like using mod_*, except your HTTP comes with support for your language&#8230; almost always because it&#8217;s written in your language.  The most famous of these are Tomcat and JBoss (Java), but there are others.
</p>
<h3>State layer as an HTTP-accessible service</h3>
<p>
Adding the ability to access your state layer over HTTP changes things significantly:</p>
<ul>
<li>
            Your database can now be accessed from any machine anywhere using the Internet, and it&#8217;s almost impossible to keep this from happening.
        </li>
<li>
            Your database can now be accessed by Javascript running on the user&#8217;s machine.
        </li>
<li>
            You are now running more HTTP servers, and every thing that was once just X database hits is now X database hits + 1 HTTP hit.
        </li>
</ul>
<p>
The other points are interesting, but it&#8217;s the 3rd that I think a lot of people gloss over.  Yeah it&#8217;s great that Javascript can access my database, OK, but isn&#8217;t it still&#8230; making a connection to a server?
</p>
<h4>Life-cycle of a request using a database.</h4>
<ol>
<li>Webserver receives HTTP request, forwards to webapp.</li>
<li>Webapp gets some stuff from the database.</li>
<li>Webapp figures out what template to render from HTTP request.</li>
<li>Webapp renders the template w/ information from database.</li>
<li>Webapp sends data back to webapp as an HTTP response.</li>
<li>Webserver sends HTTP response.</li>
</ol>
<h4>Life-cycle of a request using an HTTP-accessible state layer.</h4>
<ol>
<li>Webserver #1 receives HTTP request, forwards to webapp.</li>
<li>Webapp figures out what template to render from HTTP request.</li>
<li>Webapp sends data back to webserver #1 as an HTTP response.</li>
<li>Webserver #1 sends HTTP response.</li>
<li>Webserver #2 receives HTTP request for state information.</li>
<li>Webserver #2 does some black magic, comes up with information.</li>
<li>Webserver #2 sends state information as an HTTP response.</li>
</ol>
<p>
Now all this is obviously pretty simplified to prove a point, but a socket connection is a socket connection, and if this &#8220;HTTP-accessible state layer&#8221; is just a RESTful layer on top of an RDBMS, you&#8217;ve just added a bunch of overhead.  Furthermore, your state info requests are no longer being made over a nice, low-latency LAN, oh no, they&#8217;re travelling the full length of the Internet.
</p>
<p>
So if your page requests JSON via an XHR just <b>once</b>, you&#8217;ve halved your potential reqs/sec right away&#8230; and that&#8217;s if your state layer HTTP server/backend is as fast as your normal HTTP server (they usually aren&#8217;t, and if they&#8217;re just a layer on top of your old state layer they&#8217;re not saving any time either&#8230; but the minimal amount of data being transferred helps somewhat).  You&#8217;re also running more HTTP servers meaning higher CPU/RAM requirements and higher overhead in general.
</p>
<p>
It&#8217;s possible that the gains made from pulling out state layer stuff from your backend into a separate, HTTP-accessible service are bigger than the losses sustained from running more services and generating more requests&#8230; but I kinda doubt it.  Then again with some kind of cache system it might not matter.  It&#8217;s also conceivable that the state layer isn&#8217;t using HTTP as an access protocol, but some sort of local socket interface with less overhead.
</p>
<p>
And yeah I know a lot of people are just adding on JSON/XML services to their backends, but I honestly don&#8217;t know what the benefit of that is from a performance standpoint.  Even if you&#8217;re using JSON, you can have your controller make the state layer info request, serialize to JSON (if necessary), and send it to the template engine as a variable&#8230; which ultimately saves an extra HTTP connection as well as whatever crap your JSON/XML service does whenever it runs.  The only real uses I see for this kind of thing are:</p>
<ul>
<li>Javascript apps like Gmail.</li>
<li>Pages that use AJAX so they don&#8217;t make the browser refresh.</li>
<li>Allowing sites access to your data.</li>
<li>Allowing sites control over your services (JSON/XML-RPC, etc.).</li>
</ul>
<p>But certainly I don&#8217;t see it as a replacement for backend state layer management.
</p>
<h2>I am tired of this!</h2>
<p>
I think I&#8217;ve got enough to ponder for a while.  I was flirting with the idea of a controller-less framework that used some kind of HTTP-accessible state layer in conjunction with Javascript templates&#8230; which still sounds badass!  But when you consider your HTTP server is serving your templates, then serving data to those templates in separate requests, it kind of loses its luster.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/napkins.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/napkins.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/napkins.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/napkins.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/napkins.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/napkins.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/napkins.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/napkins.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/napkins.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/napkins.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/napkins.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/napkins.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/napkins.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/napkins.wordpress.com/138/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=138&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://napkins.wordpress.com/2009/03/16/what-is-up-in-web-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a75b9492708c1ace8853340fe70c6c18?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Charlie</media:title>
		</media:content>
	</item>
		<item>
		<title>Rent a coder and myriad wannabes</title>
		<link>http://napkins.wordpress.com/2009/03/14/rent-a-coder-and-myriad-wannabes/</link>
		<comments>http://napkins.wordpress.com/2009/03/14/rent-a-coder-and-myriad-wannabes/#comments</comments>
		<pubDate>Sat, 14 Mar 2009 09:30:54 +0000</pubDate>
		<dc:creator>Charlie</dc:creator>
				<category><![CDATA[General Commentary]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://napkins.wordpress.com/?p=131</guid>
		<description><![CDATA[I&#8217;m a programmer and a system administrator.  I&#8217;m actually just &#8220;the computer guy&#8221; and I do whatever I&#8217;m asked to do&#8230; or do whatever I need to do so I can do what I&#8217;m asked to do.  It turns out I have a lot of jobs.  I don&#8217;t make great money ($32,000/yr. before taxes) but [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=131&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a programmer and a system administrator.  I&#8217;m actually just &#8220;the computer guy&#8221; and I do whatever I&#8217;m asked to do&#8230; or do whatever I need to do so I can do what I&#8217;m asked to do.  It turns out I have a lot of jobs.  I don&#8217;t make great money ($32,000/yr. before taxes) but I&#8217;m poorly-educated and I accept the world as it is.</p>
<p>So if you give that 5/7 days are for working and I generally take around 4 weeks of vacation a year (perks!), I end up working around 240 days a year.  Which ends up being about $130/day before taxes, and about $110/day after.  And here&#8217;s something you&#8217;ll rarely hear someone in my field say: there are long periods of time where I do nothing at all.  I&#8217;m talking on a week/month basis I really just wait for things and keep systems running.  Yeah, that&#8217;s right.  I said I&#8217;m getting paid to do absolutely nothing but show up.</p>
<p>So when you post something that&#8217;s gonna take me 3-5 days of honest-to-god work to do, as in 24-40 hours of sit down, pound it out work, goddamn man you gotta pay up.  No I am absolutely not gonna spend a whole week of free time setting up a &#8220;PHP Chat&#8221; app for you for $200.  That is fucking insulting.  When I take a shit I get paid $20, and if I were getting paid on a per/shit basis, I could probably squeeze 10 shits out in 3-4 days.</p>
<p>You know OK, sure, I can do a shitty job for $200.  I&#8217;ll login exactly once, install some junk I googled and found on Freshmeat, and swear up &amp; down not to backdoor your machines so I can run hacker schemes/porn mirroring rings that pay much better.  Shit man.</p>
<p>I know I should let it go, but I can&#8217;t.  Really, you need to bust into <a href="http://www.rentacoder.com">Rent-a-coder</a> (or however they spell it) and look at the low tier of things &#8211; &#8220;Small Business Project&#8221; they call it.  For $100 or less you can:</p>
<ul>
<li>Redesign a website</li>
<li>Write a Facebook application</li>
<li>Shoot a YouTube video</li>
<li>Create an MMORPG account reselling/buying site</li>
</ul>
<p>I kid you not, even sitting down for the 1st (serious, of course) discussion with any of these projects would cost $500.  Unless you want me to:</p>
<ul>
<li>Lie to you and tell you I&#8217;ll custom design everything to your spec</li>
<li>Download Drupal or whatever fuckin thing looks most ballerass</li>
<li>Rootkit your machine hopelessly and throw it up on proxy lists</li>
</ul>
<p>And hey, this is what a <strong>nice guy like me</strong> came up with, just because he felt insulted by your shitty, meager offer.  Imagine what the assholes who actually do shit like this for real money have going.  Word to the wise, the whole thing&#8217;s a scam.  Take yr $100, buy a used computer from your nearest University Surplus, and learn <a href="http://www.python.org">Python</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/napkins.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/napkins.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/napkins.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/napkins.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/napkins.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/napkins.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/napkins.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/napkins.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/napkins.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/napkins.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/napkins.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/napkins.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/napkins.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/napkins.wordpress.com/131/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=131&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://napkins.wordpress.com/2009/03/14/rent-a-coder-and-myriad-wannabes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a75b9492708c1ace8853340fe70c6c18?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Charlie</media:title>
		</media:content>
	</item>
		<item>
		<title>We are allowed to complain</title>
		<link>http://napkins.wordpress.com/2009/03/03/we-are-allowed-to-complain/</link>
		<comments>http://napkins.wordpress.com/2009/03/03/we-are-allowed-to-complain/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 19:30:44 +0000</pubDate>
		<dc:creator>Charlie</dc:creator>
				<category><![CDATA[General Commentary]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://napkins.wordpress.com/2009/03/03/we-are-allowed-to-complain/</guid>
		<description><![CDATA[I&#8217;m not an expert on personalities in the Python community, but this guy Armin says basically this: &#34;I fuckin hate the Python stdlib because it&#8217;s written like it&#8217;s 1995&#34; And some Jesse guy says this in the comments: &#34;Wow, for someone who hates the stdlib so much, I only see 3 bugs filed by you, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=130&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m not an expert on personalities in the Python community, but this guy Armin says basically this:</p>
<p>&quot;I fuckin hate the Python stdlib because it&#8217;s written like it&#8217;s 1995&quot;</p>
<p>And some Jesse guy says this in the comments:</p>
<p>&quot;Wow, for someone who hates the stdlib so much, I only see 3 bugs filed by you, and 10 you&#8217;re +noisy on. I know you found a bug (and a bad one at that). But coming out and declaring the stdlib crap because of issues you have with &#8216;Cookie, cgi, and urllib&#8217; is annoying, especially as I don&#8217;t see patches from you.</p>
<p>Maybe I missed them in the tracker.&quot;</p>
<p>I&#8217;m not here to argue for the value of complaining.  I am here to say that we are allowed to declare that something objecively sucks without doing anything to fix it.</p>
<p>CNN sucks.  I&#8217;m not gonna become Dan Rather and lead a news revolution, nor am I going to become Mark Cuban, buy CNN, fire all the hacks and do something useful.  CNN can suck and I&#8217;m not required to lead a crusade to change it to recognize and express that fact.</p>
<p>OK later Jesse says this:</p>
<p>&quot;Sorry Armin, I think that:</p>
<p>1&gt; You&#8217;re smart enough to know the stdlib isn&#8217;t going to get thrown out because you don&#8217;t like the code, given that it helps plenty of people get things done.</p>
<p>2&gt; As for the fix time, again &#8211; while you need a fix now, why not push that fix into python-core rather than not? Python is your language as much as it is mine, or any other person&#8217;s &#8211; help fix what broken, or work on enhancement.</p>
<p>3&gt; You&#8217;re smart, we all know this, and so asking for you to contribute to the language and improvement of the standard lib isn&#8217;t silly. Instead, you&#8217;re sitting there calling it stupid, which isn&#8217;t very becoming.</p>
<p>So, given the bug you opened was already fixed, why don&#8217;t you file some more since you know that the stdlib is totally broken?&quot;</p>
<p>So the argument narrows a little to, &quot;Hey, you&#8217;re a smart guy who does stuff like this for a living.  Isn&#8217;t it a little snobbish and rude to trash someone else&#8217;s work like that?  Especially when you could easily fix it yourself?&quot;</p>
<p>Nope.  Again, complaining is free.  I mean sure, Jesse&#8217;s free to do what he did too but no one&#8217;s criticizing his response.  Fundamentally people need to be able to express their true thoughts about things without responsibility, otherwise we get tangled up in the&#8230; decorum of things instead of having an objective and clear discussion.</p>
<p>In this specific case there&#8217;s a basic disagreement between Armin &amp; Jesse regarding what Python&#8217;s stdlib should be; Armin is for a smaller, leaner stdlib with things that are platform-dependent or expected in a modern language (threads, collections, etc.), whereas Jesse likes a more &#8220;batteries-included&#8221; approach.  Having some experience with what the Python stdlib is now, I have to say I&#8217;m inclined to agree with Armin here.</p>
<p>The Python stdlib sprawls outward in a ridiculous fashion.  There is little consistency in style, implementation or recommended methods of extension and use.  Many of the libraries have fatal bugs, making them useful for little more than one-off scripts.  Yeah it&#8217;s cool I can script a webserver in 2 lines or whatever it is.  No it&#8217;s not cool that it&#8217;s uselessly slow and only handles GET &amp; POST, besides duplicating the implementation details of other modules in the stdlib.</p>
<p>It would be far more useful for Python to implement the basic socket, forking, threading and logging details, and leave it up to a PyServer package to implement typical resident services, like imap, ftp and http daemons.  The main benefit is that PyServer isn&#8217;t in the stdlib, so it&#8217;s free to fix its own bugs and grow its own features separate from Python itself.</p>
<p>By the way, PyServer already largely exists in numerous forms; the most famous is probably Twisted, which took it upon itself to implement a reasonable concurrency system even if it&#8217;s much more complicated than it should be.  When you try and Google for the reason Twisted isn&#8217;t a part of the stdlib, or even its famous Deferred object, you&#8217;ll find that the reason is Twisted has a markedly different development cycle and philosophy than Python does.  It is fundamentally a separate project which is based on Python, but not part of it.</p>
<p>The final exchange between Jesse &amp; Armin is instructive:</p>
<p>&quot;@Armin I realize fixing some of these issues may break existing apps, but that&#8217;s not an impossible slope. Deprecate in one rev, fix in another. I personally feel if it&#8217;s broken, or grossly incorrect, current apps be damned, we need to fix it.</p>
<p>All I&#8217;m asking for is patches and fixes for the stdlib, which isn&#8217;t going away. You&#8217;re code is pretty darned good, and I think what you&#8217;ve made great &#8211; I just want to see work towards fixing things, and less sensationalist posts that can help all of us both realize what&#8217;s broken, why, and how to fix it.</p>
<p>It&#8217;s better to be constructive and do what we can than throwing our hands up and saying &#8220;this sucks let&#8217;s go shopping&#8221;.&quot;</p>
<p>&quot;@13: If something is deeply flawed / problematic I&#8217;ll file a bug. Generally speaking I prefer to not use the standard library and build on third party libraries which adapt a lot quicker.</p>
<p>I&#8217;ll blog about that issue so that I can explain myself a bit better.&quot;</p>
<p>Yeah it&#8217;s better to be constructive, but that&#8217;s not the choice here.  It&#8217;s &#8220;be constructive&#8221; or &#8220;shut up forever&#8221;.  I agree that people constantly whining without offering anything is extremely frustrating, because whining is very easy while fixing and creating is very difficult (when done correctly), but that too is the wrong perspective.  There is so much that is broken, so much that is just bad and wrong that to hope to fix it all or even to be a part of fixing it all in any way is impossible.  Things can always improve and there are always going to be things to fix, and one shouldn&#8217;t be required to make a commitment to resolving these states before acknowledging they exist.</p>
<p>Interestingly enough, Armin is actually fixing things in his own perspective.  His thesis is that the stdlib is irreparably broken, not because it&#8217;s broken in and of itself but because of the fact that since so much code that depends upon its behavior (broken or otherwise) fixing the bugs just creates more bugs.  From Armin&#8217;s perspective, fixing the stdlib is migrating off of it onto more agile libraries so that, eventually, much of the stdlib can be deprecated and ultimately removed.  Frankly after working with much of the stdlib, I can&#8217;t say I disagree.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/napkins.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/napkins.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/napkins.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/napkins.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/napkins.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/napkins.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/napkins.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/napkins.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/napkins.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/napkins.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/napkins.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/napkins.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/napkins.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/napkins.wordpress.com/130/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=130&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://napkins.wordpress.com/2009/03/03/we-are-allowed-to-complain/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a75b9492708c1ace8853340fe70c6c18?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Charlie</media:title>
		</media:content>
	</item>
		<item>
		<title>Using NOPASSWD in sudoers on Ubuntu</title>
		<link>http://napkins.wordpress.com/2009/02/18/using-nopasswd-in-sudoers-on-ubuntu/</link>
		<comments>http://napkins.wordpress.com/2009/02/18/using-nopasswd-in-sudoers-on-ubuntu/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 18:08:32 +0000</pubDate>
		<dc:creator>Charlie</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[sudo]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://napkins.wordpress.com/2009/02/18/using-nopasswd-in-sudoers-on-ubuntu/</guid>
		<description><![CDATA[A little trick, if you want to use NOPASSWD on Ubuntu for a few commands (like apt-get update, mount/umount, shutdown, etc.), you need to put your entry at the bottom, like this: %admin ALL=(ALL) ALL awesomeuser ALL=(ALL) NOPASSWD: /bin/mount, /bin/umount, /bin/shutdown Otherwise the %admin line overrides whatever you specify.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=129&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>
A little trick, if you want to use NOPASSWD on Ubuntu for a few commands (like apt-get update, mount/umount, shutdown, etc.), you need to put your entry at the bottom, like this:
</p>
<pre>
%admin ALL=(ALL) ALL
awesomeuser ALL=(ALL) NOPASSWD: /bin/mount, /bin/umount, /bin/shutdown
</pre>
<p>Otherwise the %admin line overrides whatever you specify.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/napkins.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/napkins.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/napkins.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/napkins.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/napkins.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/napkins.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/napkins.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/napkins.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/napkins.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/napkins.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/napkins.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/napkins.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/napkins.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/napkins.wordpress.com/129/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=129&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://napkins.wordpress.com/2009/02/18/using-nopasswd-in-sudoers-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a75b9492708c1ace8853340fe70c6c18?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Charlie</media:title>
		</media:content>
	</item>
		<item>
		<title>ORM Madness</title>
		<link>http://napkins.wordpress.com/2009/01/13/orm-madness/</link>
		<comments>http://napkins.wordpress.com/2009/01/13/orm-madness/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 17:36:00 +0000</pubDate>
		<dc:creator>Charlie</dc:creator>
				<category><![CDATA[General Commentary]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sqlalchemy]]></category>

		<guid isPermaLink="false">http://napkins.wordpress.com/2009/01/13/orm-madness/</guid>
		<description><![CDATA[You want to know my huge beef with Python web frameworks and ORMs and software that &#34;makes developers&#8217; lives easier&#34;? This junk: from sqlalchemy.orm import defer, lazyload posts = Post.query.options(defer('text'), lazyload('author')).limit(50).all() OK, how the hell does the implementation of this work? As far as I know, there&#8217;s 6 points of magic: Post isn&#8217;t really a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=120&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>
You want to know my huge beef with Python web frameworks and ORMs and software that &quot;makes developers&#8217; lives easier&quot;?  This junk:
</p>
<p><code>
<pre>
from sqlalchemy.orm import defer, lazyload
posts = Post.query.options(defer('text'), lazyload('author')).limit(50).all()
</pre>
<p></code></p>
<p>
OK, how the hell does the implementation of this work?  As far as I know, there&#8217;s 6 points of magic:
</p>
<ul>
<li>Post isn&#8217;t really a post, it&#8217;s a <i>thing</i> that lets you query a post collection.</li>
<li>Post.query isn&#8217;t an attribute, it&#8217;s a function&#8230; at least it presumably returns something, or it might be a method that does nothing unless some other magic thing happens&#8230; THEN it&#8217;s a function.</li>
<li>Post.query.options also (again, presumably) isn&#8217;t an attribute, nor is it a method, it&#8217;s actually also a function that&#8230; lets you add options to a query but also returns the query results?</li>
<li>Post.query.options will take (positional, non-positional&#8230;?) arguments that accept the things that defer() &amp; lazyload() return&#8230; whatever that may be.  In fact, who knows what the hell defer() &amp; lazyload() do, or even what the difference is.</li>
<li>Post.query.options.limit() is also some magical thing that&#8230; oh it&#8217;s actually an option but we think it&#8217;s special, so it gets its own completely ambiguous function/method thing.  Swell.</li>
<li>Post.query.options.limit.all()&#8230; OHHHHH.  THIS is what actually returns something I care about!</li>
</ul>
<p>
Also, it&#8217;s godawful ugly.  What if my columns aren&#8217;t simple like &#8216;text&#8217; and &#8216;author&#8217;, but more like, &#8216;suicidal_frags_against_division&#8217; and &#8216;suicidal_frags_against_conference&#8217;?
</p>
<p><code>
<pre>
from sqlalchemy.orm import defer, lazyload
games = Game.query.options(defer('suicidal_frags_against_conference'), lazyload('suicidal...
</pre>
<p></code></p>
<p>
Yeah that&#8217;s way too long (abbreviated to avoid messing up my blog layout), or maybe we could uh, split somewhere like this:
</p>
<p><code>
<pre>
from sqlalchemy.orm import defer, lazyload
games = Game.query.options(defer('suicidal_frags_against_conference'),
                           lazyload('suicidal_frags_against_division')).limit(50).all()
</pre>
<p></code></p>
<p>
Bleck, still &gt; 80 columns.  Well how would Django do it?
</p>
<p><code>
<pre>
from sqlalchemy.orm import defer, lazyload
games = Game.query.options(\
    defer('suicidal_frags_against_conference'),
    lazyload('suicidal_frags_against_division')).limit(\
    50).all()
</pre>
<p></code></p>
<p>
AHHHH MY EYES, THEY 8L33DZ0RZ!  Let&#8217;s try this SQLAlchemy thing.
</p>
<p><code>
<pre>
from sqlalchemy.orm import defer, lazyload
games = Game.query.options(defer('suicidal_frags_against_conference'),
                           lazyload('suicidal_frags_against_division'))\
                           .limit(50).all()
</pre>
<p></code></p>
<p>
GAH!  Why are we splitting in function arguments AND before a function/method/attribute thing?  JESUS WHEN WILL IT STOP?
</p>
<p>
You know what&#8217;s even worse?  You actually have to define what can be deferred &amp; lazyloaded in your models &#8212; so if your needs/schema change, or you just forgot to do it, you get to dig through the 100s of lines of magic model code you wrote and replace some stuff, and restart whatever app you&#8217;re using that uses the ORM.  So on top of defining the &quot;ability to defer or lazyload certain columns/attributes of my models&quot; in the models themselves, I have to import some magic methods/functions/callables from the ORM to specify that I want this behavior, the model provides none of that functionality itself.  Really guys, I don&#8217;t know if I can take more awesomeness, I might have reached my quota here.
</p>
<p>&quot;OK wise guy, what would you do if you&#8217;re such a genius?&quot;</p>
<p>
Oh I&#8217;ll tell you what I&#8217;d do.
</p>
<p><code>
<pre>
from BadAss.models import Games
games = Games.get(limit=50,
                  defer=['suicidal_frags_against_conference'],
                  lazyload=['suicidal_frags_against_division'])
</pre>
<p></code></p>
<p>
This implementation has the following benefits over SQLAlchemy&#8217;s:
</p>
<ul>
<li>I can read it without crying.</li>
<li>I don&#8217;t have to make crazy guesses about whether I need to import a magic function/method/callable to get the results I want.</li>
<li>I don&#8217;t have to make crazy guesses about what this function does.</li>
<li>It uses a verb to signify that it&#8217;s DOING SOMETHING, and the meaning of that verb communicates the fact that a value will be returned (&quot;get&quot; in this case).</li>
<li>The semantics aren&#8217;t all jumbled up.  I&#8217;m not guessing about what&#8217;s a function or what&#8217;s a method or what magic is happening.  Even if it doesn&#8217;t work exactly how I think, the basic algorithmic logic is pretty obvious.</li>
<li>Because I know that it uses simple, basic Python types, I can pull things out into separate steps and helper variables if the function arguments just get too wide for my editor.</li>
<li>It is trivial to wrap this into gigantic meta-models that dynamically adjust the arguments to the ORM functions it calls; doing that with the SQLAlchemy implementation would be horribly convoluted and buggy.</li>
</ul>
<p>
Please God in heaven, stop this onslaught of&#8230; oh I don&#8217;t even know what it&#8217;s called, maybe Rubyisms?  Railsisms?  It&#8217;s as though as soon as Rails showed up with its clever &quot;when you read this out loud, it sounds like a sentence!&quot; voodoo, all of a sudden dynamic programmers everywhere were striving to make programming languages into human languages.  PLEASE STOP IT.  There&#8217;s a reason we use the languages in the way that we use them, and it&#8217;s because human languages are imprecise and non-standard.  Stop catering to people who are too dumb to program, stop creating entire systems that are semantically faulty and architecturally bastardized.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/napkins.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/napkins.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/napkins.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/napkins.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/napkins.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/napkins.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/napkins.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/napkins.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/napkins.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/napkins.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/napkins.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/napkins.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/napkins.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/napkins.wordpress.com/120/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=120&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://napkins.wordpress.com/2009/01/13/orm-madness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a75b9492708c1ace8853340fe70c6c18?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Charlie</media:title>
		</media:content>
	</item>
		<item>
		<title>The Future of ZDStack</title>
		<link>http://napkins.wordpress.com/2008/12/30/the-future-of-zdstack/</link>
		<comments>http://napkins.wordpress.com/2008/12/30/the-future-of-zdstack/#comments</comments>
		<pubDate>Tue, 30 Dec 2008 12:12:42 +0000</pubDate>
		<dc:creator>Charlie</dc:creator>
				<category><![CDATA[ZDaemon]]></category>
		<category><![CDATA[ZDStack]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[statistics]]></category>

		<guid isPermaLink="false">http://napkins.wordpress.com/2008/12/30/117/</guid>
		<description><![CDATA[So after working with the IDL site, I&#8217;ve really got a better handle on ZDaemon CTF statistics. What Are ZDaemon CTF Statistics? During a CTF match, really only 3 things can happen (that are logged, anyway): A player frags/is fragged A player touches a flag A player returns a flag All other events are modifications [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=117&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>So after working with the IDL site, I&#8217;ve really got a better handle on ZDaemon CTF statistics.</p>
<h2>What Are ZDaemon CTF Statistics?</h2>
<p>During a CTF match, really only 3 things can happen (that are logged, anyway):</p>
<ul>
<li>A player frags/is fragged</li>
<li>A player touches a flag</li>
<li>A player returns a flag</li>
</ul>
<p>All other events are modifications on these basic 3 events; a death is a frag in reverse, a flag capture is a successful flag touch, and so on.</p>
<p>We can then build quite a lot of state into these events.  Things like:</p>
<ul>
<li>Score</li>
<li>Home/Enemy Flag State (taken or not taken)</li>
<li>Whether the player is holding the other team&#8217;s flag</li>
<li>Etc.</li>
</ul>
<p>The IDL site is doing this, however, ZDStack&#8217;s stats are quite a ways behind.  I might add this for 0.11; considering 0.10 took me over 8 months to release, I think I can be a little more ambitious in my releases.  I&#8217;m a little torn between releasing little incremental changes often, or releasing larger changes every 6-8 months or so.  I think I find the latter more rewarding, releasing smaller, more frequent changes might cause me to get sloppy in my testing.  The original idea is to get all the &#8220;features&#8221; in by 0.11, so I can then concentrate on the RPC API, stability, logging/debugging/tracing, etc. in the 1.0 release candidates, however, that could all change depending upon how inspired I get.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/napkins.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/napkins.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/napkins.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/napkins.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/napkins.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/napkins.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/napkins.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/napkins.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/napkins.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/napkins.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/napkins.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/napkins.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/napkins.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/napkins.wordpress.com/117/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=117&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://napkins.wordpress.com/2008/12/30/the-future-of-zdstack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a75b9492708c1ace8853340fe70c6c18?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Charlie</media:title>
		</media:content>
	</item>
		<item>
		<title>ZDStack 0.10 is coming!</title>
		<link>http://napkins.wordpress.com/2008/12/30/zdstack-010-is-coming/</link>
		<comments>http://napkins.wordpress.com/2008/12/30/zdstack-010-is-coming/#comments</comments>
		<pubDate>Tue, 30 Dec 2008 11:56:21 +0000</pubDate>
		<dc:creator>Charlie</dc:creator>
				<category><![CDATA[ZDStack]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://napkins.wordpress.com/2008/12/30/114/</guid>
		<description><![CDATA[So I&#8217;m starting to get ZDStack 0.10 ready for release. There&#8217;s a couple of things I want to check, namely: Plugins I&#8217;m not terribly confident in the plugin system, let alone the set of default plugins that are supposed to ship with 0.10. In fact, probably the only plugins I think might work at all [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=114&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;m starting to get ZDStack 0.10 ready for release.  There&#8217;s a couple of things I want to check, namely:</p>
<h3>Plugins</h3>
<p>I&#8217;m not terribly confident in the plugin system, let alone the set of default plugins that are supposed to ship with 0.10.  In fact, probably the only plugins I think might work at all are <span style="font-family:monospace;">clean_language</span> and <span style="font-family:monospace;">unique_players</span>&#8230; and <strong>those</strong> might not even work.  Needs testing!.</p>
<h3>RPC Methods</h3>
<p>I want all the RPC methods to be fully tested.  I remember doing this a couple months ago, but it needs to be done again in light of the new player architecture (list instead of dict, basically).</p>
<h3>ZDWebStats</h3>
<p>Because it&#8217;s taken so long for 0.10 to happen, <a href="http://webpy.org">web.py</a> has actually released not just 0.30, but 0.31.  This is great news!  However, there are some incompatible changes that ZDWebStats needs to be updated for.  Additionally, I&#8217;m a little disappointed I didn&#8217;t include flag stats in the player breakdown&#8230; then again, maybe it&#8217;s because all the possible stats are included on the main stat table and such a display would just be redundant.</p>
<h3>Voting Support/Limited RCON</h3>
<p>I&#8217;m not completely gung-ho on adding voting support into ZDStack because the zserv versions that support it are buggy and crash&#8230; and their new features/bug fixes aren&#8217;t worth that.  On the other hand, I assume the day will come when the new zservs won&#8217;t crash, and it would be nice to be ready for it.</p>
<p>The interesting thing is that both of these functions can be handled by ZDStack&#8217;s plugin system, probably even better than zserv&#8217;s handling of them now.  The interface isn&#8217;t as nice, but that&#8217;s not really a huge deal.  Would I like it if zserv had some kind of little interface API?  YES!  But again, I can live without it.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/napkins.wordpress.com/114/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/napkins.wordpress.com/114/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/napkins.wordpress.com/114/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/napkins.wordpress.com/114/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/napkins.wordpress.com/114/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/napkins.wordpress.com/114/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/napkins.wordpress.com/114/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/napkins.wordpress.com/114/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/napkins.wordpress.com/114/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/napkins.wordpress.com/114/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/napkins.wordpress.com/114/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/napkins.wordpress.com/114/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/napkins.wordpress.com/114/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/napkins.wordpress.com/114/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=114&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://napkins.wordpress.com/2008/12/30/zdstack-010-is-coming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a75b9492708c1ace8853340fe70c6c18?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Charlie</media:title>
		</media:content>
	</item>
		<item>
		<title>How I setup Django to serve at the domain root, and saved the day</title>
		<link>http://napkins.wordpress.com/2008/12/23/how-i-setup-django-to-serve-at-the-domain-root-and-saved-the-day/</link>
		<comments>http://napkins.wordpress.com/2008/12/23/how-i-setup-django-to-serve-at-the-domain-root-and-saved-the-day/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 17:46:31 +0000</pubDate>
		<dc:creator>Charlie</dc:creator>
				<category><![CDATA[General Commentary]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[virtualdomain]]></category>
		<category><![CDATA[virtualhost]]></category>

		<guid isPermaLink="false">http://napkins.wordpress.com/2008/12/23/how-i-setup-django-to-serve-at-the-domain-root-and-saved-the-day/</guid>
		<description><![CDATA[Whew! I spent an entire day figuring this thing out. Wow! OK, here it goes. I had developed my site under a development url, http://blah.blahblah.org/dev/. So now I want to remove the &#8216;dev/&#8217;. Well that&#8217;s easy right? Here&#8217;s how I have my stuff configured: (also I don&#8217;t mean to plug my site over and over [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=108&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Whew!  I spent <strong>an entire day</strong> figuring this thing out.  Wow!  OK, here it goes.</p>
<p>I had developed my site under a development url, http://blah.blahblah.org/dev/.  So now I want to remove the &#8216;dev/&#8217;.  Well that&#8217;s easy right?  Here&#8217;s how I have my stuff configured:</p>
<p>(also I don&#8217;t mean to plug my site over and over again, I&#8217;m just too lazy to change all the domains)</p>
<h2>lighttpd.conf</h2>
<pre>
$HTTP["host"] == "www.intldoomleague.org" {
    server.document-root = "/srv/domains/www.intldoomleague.org"
    fastcgi.server =
        ( "/idl_django.fcgi" =&gt;
             ( "main" =&gt;
                 ( "socket" =&gt; "/tmp/idl_django.sock",
                   "check-local" =&gt; "disable",
                   "bin-path" =&gt; "/srv/idl_django/idl_django.fcgi",
                 )
             )
    )
    url.rewrite-once = ( "^/(.*)$" =&gt; "/idl_django.fcgi/$1" )
}

$HTTP["host"] == "static.intldoomleague.org" {
    server.document-root = "/srv/domains/www.intldoomleague.org/static"
}

$HTTP["host"] == "forums.intldoomleague.org" {
    server.document-root = "/srv/domains/www.intldoomleague.org/forums"
}

$HTTP["host"] == "wiki.intldoomleague.org" {
    server.document-root = "/srv/domains/www.intldoomleague.org/wiki"
}
</pre>
<p></p>
<h2>settings.py</h2>
<pre>
###
# Lots of other junk
# ...
###
FORCE_SCRIPT_NAME = ''
MEDIA_ROOT = '/srv/domains/www.intldoomleague.org/static/media'
MEDIA_URL = 'http://static.intldoomleague.org/media/'
BASE_URL = 'http://www.intldoomleague.org'      # this is a custom addition
STATIC_URL = 'http://static.intldoomleague.org' # this is a custom addition
ADMIN_MEDIA_PREFIX = 'http://static.intldoomleague.org/admin_media/'
</pre>
<p></p>
<h2>idl_django.fcgi</h2>
<pre>
#!/usr/bin/env python

import os
import sys

sys.path.insert(0, '/srv')
os.chdir('/srv/idl_django')
os.environ['DJANGO_SETTINGS_MODULE'] = 'idl_django.settings'
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")
</pre>
<p></p>
<p>And finally, I added a symlink:</p>
<pre>
ln -s /usr/lib/python2.5/site-packages/django/contrib/admin/media \
      /srv/domains/www.intldoomleague.org/static/admin_media
</pre>
<p></p>
<p>I know, it seems so easy right?  I could probably do a couple things differently, like using Lighttpd&#8217;s simple VHost stuff rather than $HTTP["host"] conditionals but honestly I kind of like the concept of the webserver creating that abstraction itself, as opposed to organizing it all in folders.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/napkins.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/napkins.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/napkins.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/napkins.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/napkins.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/napkins.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/napkins.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/napkins.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/napkins.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/napkins.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/napkins.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/napkins.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/napkins.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/napkins.wordpress.com/108/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=napkins.wordpress.com&amp;blog=2015057&amp;post=108&amp;subd=napkins&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://napkins.wordpress.com/2008/12/23/how-i-setup-django-to-serve-at-the-domain-root-and-saved-the-day/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/a75b9492708c1ace8853340fe70c6c18?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Charlie</media:title>
		</media:content>
	</item>
	</channel>
</rss>
