Two Birds, One Hot Code Load

I bet there are a lot of people still questioning the utility of hot code loading. Especially in the web app field, it can seem a little gratuitous. PHP apps don’t need any special hot load facility – the script just gets reread from disk every once in a while.

Well, even if we ignore that there are likely parts of web apps that do need to run all the time, and are not just executed at request time, there’s still the web server to think about. And, guess what I did last week.

Yaws provides lots of nice utility functions. One in particular is yaws_api:htmlize/1, which takes an IoList as an argument, and returns the “same” list with the four big offenders (ampersand, double-quote, less-than, and greater-than) replaced with their HTML entities (& et al.). This function does exactly what you need when serving HTML directly to a modern web browser.

Unfortuntately, htmlize/1 doesn’t work perfectly when sending “FBML” to Facebook. During Facebook’s translation, it converts all characters with ASCII values greater than 127 to unrecognizeable characters, which come out as some form of “?” in a browser.

The fix is simple – just HTML-encode all characters over 127 as HTML entities of the form &#X;, where X is the decimal representation of the ASCII value. In Yaws 1.68, just add the following two lines just before yaws_api.erl:590 (the line with the guard for integer(X)):

htmlize_l([X|Tail], Acc) when integer(X), X > 127 ->
    htmlize_l(Tail, [$;, integer_to_list(X), $#, $&|Acc]);

Compile the new code by running make in the base directory of the Yaws source. If you’re running Yaws from a directory other than the source directory, copy ebin/yaws_api.beam to that other ebin directory.

Edit: See dbt’s comment for a way to skip the next paragraph in the simple case.

Now for the magic. My prefered way to load new code is to open a console to the web server’s erlang node. First, run “erl -sname Name”, where Name is any name other than that of your webserver. Once erl starts up, type C-g (control-g, for you non-Emacs-ers). You’ll be asked for a “User switch command”. Typing “h” will get you help here, but what you actually want to do is type “r yaws@host”, where “yaws@host” is the node name of the webserver’s erlang node. Typing “j” should now show two shell sessions. Connect to the second one with “c 2″.

Now that you’re connected to your web server’s erlang node, just type “l(yaws_api)” to load the new code. Any module calling into the yaws_api module will now automatically use the new code. Meanwhile, any code that was in the middle of a yaws_api module call will finish the call with the old code.

Edit: You won’t need the next paragraph either, if you followed dbt’s instructions.

When you’re done mucking about (I know you’ve just spent the last half hour figuring out what other bits of your webserver you can touch from here), type C-g again, then kill the remote console with “k 2″. Connect back to your first console with “c 1″, then exit it in the normal manner.

So, voila, Á now comes out of htmlize/1 as Á. International beer names show up properly in Facebook, and (oh boy!) BeerRiot Local now works in IE6 (which couldn’t parse those letters from the XML tag file). Two birds, one stone, I love it.

On a couple of side notes:

Thanks for the versioning system suggestions. I’ve settled on Mercurial for now, and I’m quite happy with it so far. Bit of a pain upgrading Python versions, but I probably should have done that long ago anyway.

And, I’ve been doing more than just building a website around beer this summer. I’ve also been growing my own ingredients! I made my first hop harvest earlier this week. It was only an ounce wet, which turned into about 1/8 oz. dry, but I was proud to have some success anyway. Here’s the proof:

Cascade hops growing in my back yard

About these ads

5 comments so far

  1. dbt on

    I love that stuff. You can also use -remsh remotenode when starting erl to avoid having two shells, but when the ability to open up multiple consoles to multiple servers…. awesome when you’re doing clustering.

  2. Bryan on

    dbt: That will teach me not to have the man pages for erl installed correctly. You’ve just simplified my typical build process by more keystrokes than I thought possible.

    Before I figured this process out, I was calling spawn/4 to run all my compile/admin scripts remotely.

    I suppose each method has its place. Thanks for the tip.

  3. Mrs. BeerRiot on

    Hops dehydrating in the kitchen, brewing gadgets spilling out of the “beer nook” in the entryway, empty bottles stacked waist-high waiting for the next bottling, “beer towels” as a subset of our linens…we’re a bit obsessed with beer here in the BeerRiot household.

    Yesterday, Bryan selected new shampoo based on the presence of malt extract in the ingredient list. It’s a good thing that I love Bryan as well as beer.

  4. Idetrorce on

    very interesting, but I don’t agree with you
    Idetrorce

  5. Doing it Live « BeerRiot Blog on

    […] dynamic nature also came in useful for me on BeerRiot last night. I’ve blogged about hot code loading before, but last night I dipped into the world of OTP applications and […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: