Skip to content

New Music

24-Mar-12

It’s very hard for me to find new music. When I do find something I like, I consume it thoroughly, draining it of whatever is new and pure until it and I are become one. Like a vampire, or Tetsuo.

Over the last couple of years, more and more music has been making its way online. That and the success of bands like the Arcade Fire means that, while once the problem was a dearth of decent music, it’s now finding enough time to feed.

Coachella is coming up next month, sort of forcing the issue. And then there was sxsw, and it seems to be the season for releasing new material.. This stuff is hard to keep on top of. So, without further ado, my favorite way of assuaging my pseudo-ocd.

Vetted and thoroughly enjoyed (playlist)

  • Miike Snow
  • Purity Ring
  • Grimes
  • Rich Aucoin
  • Cloud Nothings
  • Dirty Ghosts
  • Japandroids

In the hopper

  • Poliça
  • Chairlift
  • We Were Promised Jetpacks
  • Wavves
  • Girl
  • Deerhunter
  • Zorch

ATOM-style REST endpoints with tipfy/werkzeug

04-Nov-10

I’m very used to and (somewhat) pleased with how Routes let’s you set up REST endpoints, so I was very irked to discover that Tipfy does not support the notion of a resource.

Routes will let you do something like

map = routes.Mapper(...)
map.resource('teapot' , 'teapots')

which will create a mapping like

GET     /teapots    -> controllers.teapots.TeapotController.get()
GET     /teapots/1  -> controllers.teapots.TeapotController.show(1)
PUT     /teapots/1  -> controllers.teapots.TeapotController.edit(1)
POST    /teapots    -> controllers.teapots.TeapotController.create()
DELETE  /teapots/1  -> controllers.teapots.TeapotController.delete(1)

The way Tipfy dispatch works, however, is by calling the http request method attribute on the matched handler

handler = request.rule.handler
#...
method = request.method.lower().replace('-', '_')
return handler(self, request)(method, **request.rule_args)

As you can see, this doesn’t allow for a “show” method, etc. on your handler.

The solution I’m going with for now is a base class called RestHandler:

class RestHandler(RequestHandler):
 
    def __call__(self, method, *args, **kwargs):
        """Translate HTTP methods to ATOM Publishing Protocol-esque endpoints"""
 
        try:
            if method == 'get':
                if len(args) or len(kwargs):
                    return self.show(*args, **kwargs)
                else:
                    return self.get()
 
            if method == 'post':
                return self.create()
            if method == 'put':
                return self.edit()
        except AttributeError, e:
            raise werkzeug.exceptions.MethodNotAllowed(method)
 
        return super(RestHandler, self).__call__(method, *args, **kwargs)

Your handlers can inherit from this to implement something similar to the ATOM Publishing Protocol

Update: Ian Eure has done something similar to Decoroute, which you might want to check out if you prefer using decorators

Modern Memcached Client

22-Oct-09

After a year or so of dormancy I’m finally inspired to write a blog post. This is my first post ever, so please excuse the coarseness. Plausibly enough, this one will be about Memcached, specifically how I implemented a client for TV.com, where I currently work.

The existing client was written in 2003 in PHP, which means it’s been around since the beginning, and is implemented at the highest level of the application stack (slow!). It also means that none of the advancements that have been made were available to us. The modulo hashing it uses was really crippling us, since every time we added or removed a mcd server from the pool, all existing keys would invalidate and our databases would get clobbered. Because of some of the infrastructure changes we were making, that would have happened quite often. More on this below.

Andrei Zmievski’s PHP libmecached library (which wraps the c libmemcached library) went stable right around the time we were considering this, so we jumped at the chance. This client was the obvious choice for several reasons:

  1. consistent key hashing
  2. atomic add/cas operations
  3. asynchronous get/set requests
  4. a modern command set for interfacing with memcached

Before I get in to the details of implementing the new client, I want to take a minute to talk about consistent key hashing.

Consistent hashing has been around for quite  a while (pdf). It offers significant advantages over modulo hashing if the membership of your pool is uncertain. To illustrate, I graphed what happens with both forms of hashing when pool membership changes from the expected 16 ports (represented by the vertical bar).

modulo key hashingConsistent Key Hashing

You can immediately see that with consistent hashing you get a predictable, linear degradation as membership fluctuates.

Implementing the Client

The common concern everyone has to deal with when working with memcached is how to abstract away the race conditions endemic to concurrent systems. There are lots of solutions to this, most of which involve mutual exclusions. The problem with that, though, is that locking involves some small amount of overhead (which is why Terry wanted its use to be proactive). Getting and setting the semaphore incurs a (for the vast majority of cases) negligible cost of around 5ms, and only when a key is about to expire.

One of the solutions talked about on the memcached mailing list was probabilistic timeout, thought up by the folks with too much smarts and possibly not enough to do over at IMVU. The idea is this: ask mcd to expire your key some time in the future (perhaps 24 hours), but store the real ttl and the expire-at date along with the data.

$mcd_value = array(
    'value' => $value,
    'expire_on' => time() + $ttl,
    'ttl' => intval($ttl)
);
$this->set($key, $mcd_value, 86400);

Then, when you go to retrieve the key, apply the function ƒ(x) = 100 / x + 1 to the percentage of elapsed time to the TTL. The result is the probability that the key should expire (see Figure C).

//how much time is left until value expires
$time_delta = $result['expire_on'] - time();
 
//what percentage are we to reaching the TTL?
$normal_delta = ($time_delta / $result['ttl']) * 100;
 
//the probability of clearing the cache goes to 100
//as the delta approaches 0
$probability = round(100 / (abs($normal_delta) + 1));
$clear_value = (mt_rand(1, 100) <= $probability);
prob_func

Figure C

Note that the scale of 100 was chosen somewhat arbitrarily. This is something that one could tune depending on circumstances, perhaps by creating predefined values for keys with different levels of expected use (e.g. high=1000, med=100, low=10). However, a goal of this method is to be easy to use and applicable to the common case.

If we decide that we need to expire this key, we can return Memcached::RES_NOT_FOUND to the user, who should regenerate the data and refresh the cache. In the majority of cases, this will allow us to “pre-expire” keys before they should actually expire, so there’s not a great onslaught of queries to the database every time a TTL is met.

There is of course, a race condition in this code. What happens if 4 clients all request a key which has 1% of its time left (which for a key with an hour TTL represents about 19-36 seconds, depending on how you round) before it expires? 100 / 1 +1 = 50, so each of those 4 clients has a 50% chance of clearing the key. Those are pretty good odds, so we have to expect that a certain number of clients are going to query the database.

If you’re interested in seeing how this client looks, I’ve got it up on github here. I’d like to invite any criticism you might have. The code has to fit an existing ecosystem, so I know parts of it are far from ideal.

New Site Trio

11-Aug-08

Hello, world.

I decided to start making some changes, so I started off with hosting mwhooker.com/new/org. Now, what to do with them? Hosting a blog on at least one of them seemed like a good idea. I just finished setting up WordPress for my company (Delivery Agent), and I like it as a piece of software, so that’s what you see here.

Nothing much is up on either of the domains yet (except .net…), but keep watching. I’m planning to add a lot. Not sure what, but something.