Tips for AppEngine

So, I haven’t posted much in a while. First, because after 10 articles in a row on Cocoa fundamentals, I wanted to break the run a bit. Second, because I’ve been hard at work on a project, and third, because I want to write about what I’m doing — but since that’s mostly iPhone stuff at the moment, and it’s still frustratingly-under-NDA, I can’t, dammit.

So instead I think I’ll be posting some quick tips on Google AppEngine, which is what I’ve been working with when I’m not deeply submersed in the iPhone SDK.

I imagine everyone likely to actually care has read about AppEngine by now, but the brief overview is: Google will host your Python web applications for you, on their madly-scalable infrastructure, but you have to write to their sandboxed API.

(Incidentally, whenever I think about Google’s scalable infrastructure, I picture one of Lovecraft’s towering edifices, or perhaps some vast construction nestled within The Mountains of Madness — a fragile mind ascending non-Euclidean spires, clinging, barely, to structure and sanity alike — he cries out, words whipped away by the forces raging around him “my God — the entities! The uncountable Entities! “)

First, a Really Stupid Mistake that’s easy to make and hard to pick up on. I probably ought to be embarrassed about this, but hey, my loss is your gain:

Missing Main

From the top, AppEngine looks quite sane, actually. You supply a config file that maps URLs (via regexp) to handler scripts, which are run in standard CGI fashion. If you want FCGI-style caching, which is frankly recommended, you can simply define a main() function — behind the scenes, AppEngine detects this and, subject to space constraints, keeps your script in memory, and for subsequent HTTP requests, it simply calls the main() function directly without reloading anything. This Is Good.

However, if you have a brief muppet moment, and forget the all-important:

python

boilerplate
if __name__=="__main__": main()

…you’ll get a really awkward (though, in retrospect, quite explicable) result: The first time that script is called, nothing happens — no error, no page, just 200 OK and an empty screen. The second call, however, will work perfectly — as will every single call from then on — until you change the script.

At which point, AppEngine knows it needs to reload the script from scratch, instead of calling main(), so nothing happens, again. Just for that one, lonely invocation — after which, normal service resumes.

Giving you an intermittent bug that you never quite seem to fix — especially as people tend to develop “blindness” for unchanging boilerplate stuff that just sits there at the end of the file, and that you rarely need to actually look at. Much like banner ads.