Monday, 17 September 2018

ScalaCache - conditional caching

Sometimes it's important to avoid caching some subset from return values. It's easy to implement it using Memoization method memoizeF. When using M[_] like Future - the Failed case won't be cached - and it's possible to convert any value to Failed with special exception marker that contains the value itself and in meantime blocking it from been cached.

Sometimes it's preferable to avoid caching some subset of possible values without deviation to failed case of higher kind wrapper. In case if this condition can be delineated by predicate and you don't want to play with implicit mode: Mode[F] you can mixing small trait to your cache:
import com.github.benmanes.caffeine.cache.Caffeine
import scala.concurrent.duration.Duration
import scalacache._
import scalacache.caffeine.CaffeineCache
trait Predicate[Repr] extends AbstractCache[Repr] {
protected def shouldCache: Repr => Boolean
abstract override def doPut[F[_]](key: String, value: Repr, ttl: Option[Duration])(implicit mode: Mode[F]): F[Any] = {
if (shouldCache(value)) super.doPut(key, value, ttl) else mode.M.pure(())
}
}
This example is based on Caffeine and it isn't caching negative integer values:
import com.github.benmanes.caffeine.cache.Caffeine
import scala.concurrent.duration.Duration
import scalacache._
import scalacache.caffeine.CaffeineCache
object CacheApp extends App {
val intCache: Cache[Int] = new CaffeineCache[Int](Caffeine.newBuilder().build[String, Entry[Int]]()) with Predicate[Int] {
override def shouldCache: Int => Boolean = _ > 0 }
}

No comments:

Post a Comment