I know Guava has an excellent caching library but I am looking for something more Scala/functional friendly where I can do things like cache.getOrElse(query, { /* expensive operation */})
. I also looked at Scalaz's Memo but that does not have lru expiration.
The Spray folks have a spray-caching module which uses Futures. There is a plain LRU version and a version that allows you to specify an explicit time to live, after which entries are expired automatically.
The use of Futures obviously allows you to write code that does not block. What is really cool, though, is that it solves the "thundering herds" problem as a bonus. Say, for example, that a bunch of requests come in at once for the same entry which is not in the cache. In a naive cache implementation, a hundred threads might get a miss on that entry in the cache and then run off to generate the same data for that cache entry, but of course 99% of that is just wasted effort. What you really want is for just one thread to go generate the data and all 100 requestors to see the result. This happens quite naturally if your cache contains Futures: the first requestor immediately installs a Future in the cache, so only the first requestor misses. All 100 requestors get that Future for the generated result.