mjibson/goon — pull request #29 by xStrom (2014-02-12 17:24:17+00:00)
Title: Robust memcache

I went ahead and built us a more robust memcache layer. What makes it better than the last one?

**1)** It can cope with extensive struct changes, while the old implementation didn't handle this at all.

// Say you have some structs
type User struct {
Id int64 `datastore:"-" goon:"id"`
Mail string `datastore:"mail"`
FavoriteSong Song `datastore:",noindex"`
}

type Song struct {
Artist string
Title string
}

// These work just fine ..

// .. but one day you decide you want to support multiple e-mails,
// and you don't like the look of the Song struct any longer,
// so you decide to modify the User struct:

type User struct {
IdNum int64 `datastore:"-" goon:"id"`
Mails []string `datastore:"mail"`
FavSongArtist string `datastore:"FavoriteSong.Artist,noindex"`
FavSongTitle string `datastore:"FavoriteSong.Title,noindex"`
}

The datastore part already supported migrations like this. Now the memcache layer supports it as well, so when you upload your new code, you don't have to flush memcache. The local cache doesn't really need to support this, because when you upload new code, you get a new instance, and the local cache is empty.

**2)** If in the future we also cache entities on Put, then this new system won't cache any struct variables that wouldn't be stored to the datastore.

**3)** Negative cache hits have arrived! Doing datastore requests for the same entities that don't exist over and over again can get quite expensive. No more!

In addition, I introduced versioning to the cache key generation, so that incompatible changes to the cache system won't cause any trouble. Also, I greatly improved our test coverage.