为什么Scala缓存要求我两次定义TTL?

时间:2019-07-16 21:12:53

标签: scala caching

因此,我一直在尝试加快Scala缓存的速度。我正在浏览这份文档

https://cb372.github.io/scalacache/docs/

private val thisToThatCache =
   CaffeineCache(
     Caffeine.newBuilder
       .maximumSize(4096)
       .expireAfterWrite(4, TimeUnit.HOURS)
       .build[String, String)

和此缓存调用

 import scalacache.modes.try_._
 import scala.collection.JavaConverters._

 thisToThatCache.caching(thisStr)(ttl = 4.hours)(
    fetchThatForGivenThis(thisStr)
 )

请注意,我已经两次定义了TTL,一次在缓存调用中使用4.hours,另一次基于4 TimeUnit.Hours

这有点奇怪,所以我开始研究CaffeineCache的实现

我看着这个

https://github.com/cb372/scalacache/blob/433d07ddb1249d7e6ec13fe7584a3d785be8d44d/modules/caffeine/src/main/scala/scalacache/caffeine/CaffeineCache.scala#L29

并且我意识到,无论我放置了“ Write After Write”值如何,如果缓存ttl值过期(至少应该如此),getter都会认为工件已过期。

AFAIK和底层缓存定义逐出。

所以我的问题是

  1. 对于scala缓存有两个不同的TTL定义的设计决定是什么?即驱逐和到期的概念是分开的和分别定义的吗?

为解释我的意思,doPut https://github.com/cb372/scalacache/blob/433d07ddb1249d7e6ec13fe7584a3d785be8d44d/modules/caffeine/src/main/scala/scalacache/caffeine/CaffeineCache.scala#L42的特定示例在此处创建了一个Entry对象并将其放入。该条目定义了isExpired https://github.com/cb372/scalacache/blob/dd7f9988b3b1cab20ba2a9649a51a36210065607/modules/core/shared/src/main/scala/scalacache/Entry.scala#L13,如果expiresAt为None,则其结果为false。最后,doGet:https://github.com/cb372/scalacache/blob/433d07ddb1249d7e6ec13fe7584a3d785be8d44d/modules/caffeine/src/main/scala/scalacache/caffeine/CaffeineCache.scala#L29方法检查其是否过期(如果密钥的先前doPut的expiredAt为None,则评估为false),并自认为过期后返回None。请注意,它从未查询过expireAfter ...超时。因此,如果我通过“无”,则应始终评估为未找到。

  1. 如果缓存中的expireAfterWrite

1 个答案:

答案 0 :(得分:0)

codedocs都提供了一个解释:

caching("benjamin")(ttl = None)

ttlOption[Duration],因此它应该是在

中定义的值

expireAfterWrite(4, TimeUnit.HOURS)

同时,当您使用时:

caching("benjamin")(ttl = 4.hours) // implicit conversion to Some(4.hours)

您可以覆盖特定值的默认值。实施细节取决于实施情况:

// abstract def that need to be implemented by particular cache implemetation
protected def doPut[F[_]](key: String, value: V, ttl: Option[Duration])(implicit mode: Mode[F]): F[Any]

如您所见,它收到了可选的ttl,它可以用它做任何想做的事情(甚至忽略)。默认值必须在其他位置提供,我们可以在文档中看到,这是构建器使用expireAfterWrite所做的。

长话短说,您不必两次提供ttl。如果您不想覆盖该值,只需传递None

相关问题