11

I just wonder if there is any caching solution available in Scala. I'm looking for something like it is provided by Guava in Java.

Should I use Guava too in Scala? Is there a wrapper / pimp in Scalaz or something similar? Any alternative more appropriate for Scala devs?

What Guava provides:

LoadingCache<Key, Graph> CACHE= CacheBuilder.newBuilder() .maximumSize(1000) .expireAfterWrite(10, TimeUnit.MINUTES) .removalListener(MY_LISTENER) .build( new CacheLoader<Key, Graph>() { public Graph load(Key key) throws AnyException { return createExpensiveGraph(key); } }); Supplier<Animal> singleAnimalCache = Suppliers.memoizeWithExpiration(animalFromDbSupplier(), 365, TimeUnit.DAYS); 

I need some basic cache management like in Guava.

5
  • You unhappy with stackoverflow.com/questions/3651313/… ? Commented Nov 29, 2012 at 23:12
  • @om-nom-nom this looks great, I'm looking for a memoizer (like in Guava with Supplyer), but I need some cache management like expiration, max cache size etc. I don't see that in Scalaz implementation Commented Nov 29, 2012 at 23:20
  • 5
    You wouldn't be the first to use Guava's Cache in Scala. Commented Nov 29, 2012 at 23:33
  • 2
    Twitter has a helper for MapMaker (now adapted to CacheBuilder). Instead I use CacheBuilder directly and have implicits for converting between Guava and Scala types. Commented Nov 30, 2012 at 1:15
  • Does this help? Guava caching in scala Commented May 27, 2013 at 7:30

4 Answers 4

5

We had the same requirements and ended up building wrappers around Guava. We recently open-sourced parts of the library called Mango. If you don’t mind the extra dependency you can use it like

import org.feijoas.mango.common.cache._ import org.feijoas.mango.common.base.Suppliers._ val MY_LISTENER = (remNot: RemovalNotification[Key, Graph]) => () // > MY_LISTENER : RemovalNotification[Key,Graph] => Unit = <function1> val CACHE = CacheBuilder.newBuilder() .maximumSize(1000) .expireAfterWrite(10, TimeUnit.MINUTES) .removalListener(MY_LISTENER) .build { (key: Key) => new Graph() } // > CACHE : LoadingCache[Key,Graph] = <function1> val animalFromDbSupplier = () => { // load from db new Animal() } // > animalFromDbSupplier : () => Animal = <function0> val singleAnimalCache = memoizeWithExpiration(animalFromDbSupplier, 365, TimeUnit.DAYS) // > singleAnimalCache : () => Animal = Suppliers.memoizeWithExpiration(<function0>, 365, DAYS) 
Sign up to request clarification or add additional context in comments.

Comments

5

Just adding an answer to plug my own project, but I recommend ScalaCache.

  • Supports Guava, Ehcache, Memcached and Redis (or you can plugin your own implementation if you like)
  • Simple, idiomatic Scala API
  • Support for per-element Time To Live (even for Guava, which doesn't provide that out of the box)
  • Support for auto-generation of cache keys using macro magic

https://github.com/cb372/scalacache

Comments

3

Is there a wrapper / pimp in Scalaz or something similar?

In Scalaz 7 there's Memo, which I covered a bit in learning Scalaz day 16.

It's the first thing Adam Rosien covered in scalaz "For the Rest of Us" talk, so check that out too. He's using Scalaz 6.

1 Comment

Thanks, your link seems great. But the memo provided by Scalaz doesn't seem to support expiration like Guava does
3

Using guava caching is straightforward in Scala.

import com.google.common.base._ import com.google.common.cache._ object Simple_Guava_Caches_in_Scala { def main(args: Array[String]): Unit = { // Simple scala guava cache val simpleCache1 = CacheBuilder .newBuilder() .build(new CacheLoader[String, String] { def load(key: String): String = { println(s"Simple scala guava cache, heavy work calculating $key") s"It's me $key" } }) println(simpleCache1.get("1")) println(simpleCache1.get("1")) println(simpleCache1.get("2")) println(simpleCache1.get("2")) println(simpleCache1.get("2")) // Simple scala guava supplier cache / factory println() val supplier_cache: Supplier[String] = Suppliers.memoize( () => { println("Simple scala guava supplier cache / factory, heavy work creating singleton:") "It's me" } ) println(supplier_cache.get) println(supplier_cache.get) println(supplier_cache.get) } } 

This is producing

Simple scala guava cache, heavy work calculating 1 It's me 1 It's me 1 Simple scala guava cache, heavy work calculating 2 It's me 2 It's me 2 It's me 2 Simple scala guava supplier cache / factory, heavy work creating singleton: It's me It's me It's me 

I've added this to build.sbt:

libraryDependencies += "com.github.cb372" %% "scalacache-guava" % "0.26.0" 

Would be interesting to transform the coding above to cb372's scalacache-guava. Could be even simpler/more standardized.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.