For anyone else playing with the library, you might want to sync with the repository. Yariv’s prodding caught a couple of bugs, whose fixes were committed a few days ago.
If you read the news, you’ll know that tuneups are happening behind the scenes of BeerRiot. If you came to this blog after reading that story, you’re wondering what, exactly, they are.
If I’m not feeling particularly communication-challenged, I’ll be able to explain them to you. 😉
The first tuneup is one every webmaster has heard of: denormalization. I had been using a view to select data from three tables with one call. The performance drag of that query was serious enough, though, that I’ve decided to complicate things a bit and copy the extra bits of data I need from the other tables into the main one for the query.
The speed gain is great, and, somewhat strangely, the denormalization actually cleaned up a bunch of my code. ErlyDB lacks a “one-to-one” relation, so it was impossible for me to say “each record in this view is really just a record in this other table with some extra data.” That made for a bit of hackery swinging from one type to another. Without that extra table, I think the code reads more clearly.
(Disclaimer: I’m far from being an relational database master, so it’s likely that there is a much better way to express everything I’m doing. But, I’m happy to be making what seems to be forward progress.)
The other main change is more Erlang-centric. Until now, I had been tracking sessions using a customization of the Yaws recommended session server. This is basically a central process that stores opaque data associated with an id string. Whenever your app gets a request, it pulls the cookie value out and checks with this central process to find out if there is any opaque data associated with this key. It works (quite well, in fact), but it seems like a bit of a bottle neck.
So, I’ve decided that there’s a more Erlangy way to do things. What BeerRiot is doing now is starting up a new process for each session, and saving that process id in a client cookie. Then, whenever a request comes in, if it has a cookie with a PID, we can try to contact that session’s handling process directly. No central service required.
It turns out that there’s loads of benefits to having this session hanging around beyond relieving the central service bottleneck. It can cache data, smartly (i.e. listen for updates, etc.). It’s a natural place to run background processes (like propagating live changes to durable storage). I see other potential uses, but since I haven’t tested them yet, I’ll hold my tongue to avoid getting too many hopes up. 😉
For Facebook developers: This process-session system wasn’t possible until just a few weeks ago, when Facebook started supporting cookies on the canvas page. Unfortunately, they only support them for canvas requests, and not for their “mock ajax.” For mock ajax, I’ve decided to just encode the cookie values in post parameters. It works (and it’s no more inconsistent than the rest of the Facebook Developer experience).
Update 2.Jan 18:52 EDT: If you spent any part of today poking at BeerRiot to see how the speed-ups turned out, you were probably rather dissatisfied. I just figured out that I didn’t fully rollout the update. 😛 It’s there now, and I think you’ll be much more impressed.
I’ve just committed a couple of minor updates to the erlang2facebook library that I’m sure some of you are interested in.
The first (SVN revisions 7 & 9) is an API update to follow the Facebook team’s changes to profile_setFBML. Now, instead of just passing a single chunk of FBML, containing markup for the profile box, profile actions, and mobile profile, there are three distinct fields to shove those chunks in. Sorry about the non-consecutive SVN commits. 😛
The second update (SVN revision 8 ) is intended to show how to use ErlTL better (thanks for the tips, Yariv!). I’ve created render.et, and moved all of the render_* functions from canvas_controller into it. This allows me to use the more HTML-like syntax (code efficiency), while also taking advantage of ErlTL’s automatic use of Erlang’s binaries (runtime efficiency).
Awesome! Care to step up and take credit for your accomplishments, Mark?
I’ve finally prevented distraction long enough to finish an example use of the Erlang Facebook library I posted earlier.
If you grab the source from the erlang2facebook project, you’ll know find it comes with a bunch of stuff in an “erlprints” directory. The code in “erlprints” is a near literal translation of the “Footprints” app that comes with the standard Facebook PHP library.
It’s not perfect, and there are certainly places where more Erlang-ish style could have been used, but I hope it’s good enough to give people a clue to how to use the library.
Hi all. I’ve been meaning to do this for a while now, and the requests are only becoming more frequent, so – my Erlang-Facebook bridge code is now open for use. You can get it from the erlang2facebook Google Code project.
Big warning: the main reason I wasn’t releasing this code yet is because I don’t feel that it’s documented well enough. Anyone interested in using this code will likely need to have both the Facebook doc pages and the standard Facebook PHP code open, for comparison.
I’ve been working on recreating the sample “footprints” app to package with this code. I’ll post it as soon as I do (I keep getting distracted).
Also forgive me if I’ve committed some terrible Google Code faux pas. It’s my first project hosted there, so I’m sure I missed something.
Great news this evening! The BeerRiot Facebook app has been approved for listing in the app directory. Pudding (sensitive stuff blocked out, of course):
I’ve been holding out on this for a while after the horror stories about apps and/or profiles being removed instead of just being denied. Either I successfully stayed on track, or that was all a bunch of hooey.
I hope those of you that have added the app are enjoying it. Please post reviews or send me feedback about things you’d like to see in it.
Feedback about non-Facebook functionality is welcome too, of course. 😉 Sorry there hasn’t been much there, but there is stuff coming.
As promised, here’s the post about the development process of the BeerRiot Facebook app.
Aside: Wow, rereading that last post about the Walled Gardens, I can’t believe I posted it. Totally fluffy lameness. Forgive me – this post will not be as bad.
I could very easily make this another post like others out there right now. Many people are upset about how unfinished the Facebook API is. Documentation is lacking (and only available online), specifications are weak, and test environments could be more feature-rich.
But, except for that little digression above, I promise, this is not one of those posts.
Instead, I’d really like to remark about how great it is developing this app in Erlang and Erlyweb!
There are nearly a dozen different Facebook API implementations – every object-oriented web language you can name. Facebook’s own official one is PHP5. I could have used the PHP version – Yaws comes complete with the ability to run PHP scripts. But, since the rest of BeerRiot is already in Erlyweb…
I rewrote the Facebook client in Erlang. And truthfully, it really wasn’t that bad at all. Erlang comes with very simple HTTP-communciation and XML-munging code. Hell, there’s even a simple way to compute an md5 sum. Once I figured out how to actually put together a proper POST and walk a rather verbose XML tree, the rest was just mimicking as closely as possible the official PHP scripts.
All this is not to say the process wasn’t without difficulties. Yaws’ standard url_encode proceedure doesn’t like nested io_lists very much, so I’m doing some ugly string/binary flattening. And, Facebook’s errors are nearly meaningless … but this isn’t about Facebook complaints. 😉
There are yet more benefits. Rather than dealing with cron firing up processes periodically, I have fully-supervised Erlang gen_servers up to date constantly with what data needs to be pushed out to Facebook. I can log into the running server and examine the current active sessions, monitor profile data pushes, etc.
Extending my existing Erlyweb application to handle new Facebook requests from the canvas page was even pretty simple (once I finally – I think – understood the Facebook session rules). Another controller, another view – bam!
One of my few real pains was source control. I may need to finally bite the bullet and leave CVS. I’m hearing good things about SVN. But that’s another topic.
So, chalk up one more win for Erlang/Erlyweb. Fantastic existing libraries. Quick development environment. Crazy server flexibility. I’m staying as long as I can.
Yes, I promised new things well over a week ago. My excuse is that I picked up a cold during my trip to the Middle of Nowhere that took me out of commission for a solid week. 😛 But, now that that is over…
I’ll probably talk more about how the development went in another post. Right now, though, I’m thinking over the whole “Walled Garden” argument.
For many of the apps, both the data source and the data sink reside inside the Garden – Facebookers talk to other Facebookers. For another large chunk, the data source is outside, but the sink is still inside – Stock quotes, sports scores, etc.
For BeerRiot, I’ve managed to allow the data source as well as the data sink to be on either side of the wall. Beers and comments added by Facebookers can be seen by non-Facebookers, and the other way around. Really, I’m just using Facebook something like an OpenID provider.
Of course, for some apps this isn’t necessary, and for others it may be impossible. But, it feels like this is the right way to think going forward. Using this method, there would be nothing stopping me from bridging more walls to connect more gardens together, while still keeping the web at large in the loop.
Okay, I’m about to fall asleep, and I can’t tell if this blog post is just simple fluff or not, but I’m going to post it anyway. Post in the comments if you like/dislike the FB app, what you think of Walled Gardens, or how bad this post really is.