Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lightweight caching solution in Scala?

Tags:

scala

guava

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.

like image 312
Sebastien Lorber Avatar asked Nov 29 '12 23:11

Sebastien Lorber


4 Answers

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)
like image 151
Markus Avatar answered Oct 13 '22 20:10

Markus


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

like image 37
Chris B Avatar answered Oct 13 '22 20:10

Chris B


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.

like image 25
Eugene Yokota Avatar answered Oct 13 '22 21:10

Eugene Yokota


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.

like image 41
Hartmut Pfarr Avatar answered Oct 13 '22 20:10

Hartmut Pfarr