Lightweight caching solution in Scala?

2019-04-05 05:44发布

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.

标签: scala guava
4条回答
混吃等死
2楼-- · 2019-04-05 05:59

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

查看更多
爷、活的狠高调
3楼-- · 2019-04-05 06:02

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.

查看更多
We Are One
4楼-- · 2019-04-05 06:14

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)
查看更多
放荡不羁爱自由
5楼-- · 2019-04-05 06:21

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.

查看更多
登录 后发表回答