Archive for the ‘ErlyWeb’ Category
A year in the making, almost completely rewritten, I can’t bear to hold it back any longer: today I release the new BeerRiot. Here’s a synopsis of the changes for you:
|Old Tech||New Tech|
|Erlyweb (Yaws)||Webmachine (Mochiweb)|
|Erlydb + MySQL||Hand-coded models + Mnesia + Apache Solr|
I’ll probably write a blog post about each of those rows sometime in the near future. It should be said though, the my motivation in this rewrite was not to abandon Erlyweb. Rather each piece was a deliberate attempt to get practice on something we were using at work. Erlyweb’s great, but Webmachine has a different feel. MySQL can store data fine, but it’s quite different from the key-value store I hack against all day. ErlTL’s pretty nice as templating languages go, but I needed more DOM experience.
In doing this rewrite, it’s been a real eye-opener to dig back through my early Erlang code. It wasn’t terrible, but having worked with other serious Erlang hackers all year, I notice the difference in the code I write now. The site should be much more stable now – Local/maps may even stay up for more than an hour. ;)
In that vein, though, I request that you not judge the JS running the site too harshly just yet. Just like my early Erlang was ugly, I can now tell that my early JS was ugly as well. That will be getting some cleanup soon, but I just couldn’t stand delaying the release for it.
So, go poke it and let me know what you think!
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. :P 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. :P
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?
It’s called Vimagi. It’s a way to share drawings with friends. You paint something, using his app, then show it off to people. They can watch a replay of your painting, comment, and rate your work.
Interesting to note that he’s also using some Flash and AJAX, proving ErlyWeb compatible with those technologies.
Check it out – you may even find my own [poor] artwork there, if you’re clever. ;)