Those of you who read Planet Ubuntu will doubtless have seen Jono Bacon talking about the Ubuntu Accomplishments system that he’s been working on along with a growing community of developers and testers. That system uses Ubuntu One to communicate your accomplishments to the central server that signs them off, and today I’d like to talk about why it does that.
There are a bunch of little reasons why the Accomplishments system uses
Ubuntu One, and one big reason. The big reason is this: running a
service that serves lots of people is hard. Ask anyone in a startup;
ask Twitter; ask anyone who has seen a webpage saying
504 Gateway Timeout or “We’re experiencing a lot of traffic at the
moment”. If your service becomes popular, making it able to cope with
the number of people using it is a difficult job. You need to have
servers for the web service itself, servers to fail over onto if those
get too busy or crash, servers to load-balance between them, servers to
run haproxy, servers to be the front-end, servers to cope with
unwrapping SSL, servers to run the underlying database, servers,
servers, servers. It’s hard work, and the state of the art evolves every
single day. And this is because a web service is synchronous.
You may think here, “huh?”. Take a step back. The Ubuntu Accomplishments
system lets you get
types of accomplishments: local and machine-verified. Local
accomplishments are things that only occur on your machine: you’ve just
beaten Solitaire, for example. We need not talk further of those here.
Machine-verified accomplishments are those which you are awarded (by a
script running on your machine which checks whether you’ve accomplished
them) and then that award is verified by another machine, so you can’t
lie about having them; this is things like filing your first Launchpad
bug, joining your Ubuntu loco team, and so on. The obvious way to build
this system would be to have the script which runs on your machine check
whether you’ve filed your first Launchpad bug, and then if you have,
and have that server verify that you have indeed got it. However,
imagine a world in which many many people have installed the
accomplishments system; our poor ubuntuac.com server would be
overwhelmed. We’d have to care about haproxy and load-balancing and
front-ends and nagios and so on. Now, this might actually be OK for an
Ubuntu service — the Canonical sysadmins are excellent at their jobs —
but it ought to be possible to build things without needing a whole
This is exactly the same issue that desktop programs have; if you try and do something which might take a long time, and then block waiting for the result, your application hangs. Reading a file will make your app go grey if it turns out to be a long file. The way to fix this is to be asynchronous, to request the file and have it load in the background and then call you back when it’s done. Building a popular service is similar. The way to build such a service isn’t to hit some verify URL and then wait for the result, because then the service has to rush to give you an answer, conscious that you’re waiting for it. Be asynchronous. And that’s what Ubuntu One brings to the Accomplishments system. Instead of verifying an accomplishment immediately, the Accomplishments system stores it in Ubuntu One, in a folder which is shared with the Accomplishments server. It’ll then be synced to Ubuntu One, and then to the Accomplishments server; the server can verify it at its leisure and then sign the accomplishment, and that signature is then synced back to Ubuntu One and then down to your machine. None of these steps are harmed by waiting. If your computer goes offline halfway through the process, no problem: your accomplishment will be synced when you go back online. If the Accomplishments server has a million things to do, no problem; it works through them as fast as it can manage and each will be done in turn. If Ubuntu One itself crashes, no problem; your accomplishments will sync when it recovers. If the Accomplishments server dies, no problem; you’re not waiting for a URL from it, so you’ll not get a Gateway Timeout; instead, the server will be fixed from crashing and then just carry on with its list of files, and any accomplishments that were sent to it while it was dead will still arrive.
Of course, it would be possible to build a web service and an Accomplishments client which achieved this in other ways. Have the Accomplishments client detect whether you’re online and queue up requests if you’re not; have it detect if the connection drops while it’s asking for verification; have the Accomplishments server receive a verify request URL and then return an “it’s in my queue, here’s your claim ticket” token and have the client periodically poll for that ticket or wait on a Comet connection. But that’s still a lot of effort, and it’s a lot of effort that Ubuntu One already does for you. The Accomplishments client can get all this network-y retries-y queue-y cleverness just by dropping a file in a folder, and doing it that way means that services can be built by normal mortals rather than super-network-experts. Go asynchronous and let someone else do the really difficult work for you. That’s why the Accomplishments system uses Ubuntu One, and it’s why it’s able to exist and scale without having an army of sysadmins keeping it going, no matter how many people use it.
If you’re interested in building services which work like this, chat to me, because I run the Ubuntu One app developer programme.