如何在 "Scala" 中为 Caffeine LoadingCache 编写缓存加载程序以供 "refreshAfterWrite" 工作
How to write a cache loader for Caffeine LoadingCache in "Scala" for "refreshAfterWrite" to work
Scala 应用程序用例:
我们有一个基于 Scala 的模块从全局缓存 (Redis) 读取数据并将其保存到本地缓存 (Caffeine LoadingCache)。由于我们希望异步刷新此数据,因此我们使用 LoadingCache 并将 refreshAfterWrite 持续时间设置为刷新 window of 2.second.
问题:
不是问题,但需要以下代码的帮助,这些代码会发出警告和编译时错误
警告:对于build
方法,它给出警告为Implements member load in CacheLoader (com.github.benmanes.caffeine.cache)
编译时错误1: type arguments [Int,redisToCaffeine.DataObject] conform to the bounds of none of the overloaded alternatives of value build: [K1 <: Object, V1 <: Object](x: com.github.benmanes.caffeine.cache.CacheLoader[_ >: K1, V1])com.github.benmanes.caffeine.cache.LoadingCache[K1,V1] <and> [K1 <: Object, V1 <: Object]()com.github.benmanes.caffeine.cache.Cache[K1,V1] .build[Int, DataObject](key => loader(key))
编译时错误2: wrong number of type parameters for overloaded method value build with alternatives: [K1 <: Object, V1 <: Object](x: com.github.benmanes.caffeine.cache.CacheLoader[_ >: K1, V1])com.github.benmanes.caffeine.cache.LoadingCache[K1,V1] <and> [K1 <: Object, V1 <: Object]()com.github.benmanes.caffeine.cache.Cache[K1,V1] .build[Int, DataObject](key => loader(key))
代码:
package redisToCaffeine
import scala.concurrent.duration._
import com.github.benmanes.caffeine.cache.{ CacheLoader, Caffeine, LoadingCache }
import com.twitter.finagle.stats.InMemoryStatsReceiver
import javax.annotation.Nullable
import redisToCaffeine.CacheImplicits.StatsReportingCaffeineCache
class LocalDealService {
class DataObject(data: String) {
override def toString: String = {
"[ 'data': '" + this.data + "' ]"
}
}
val defaultCacheExpireDuration: FiniteDuration = 2.second
val stats: InMemoryStatsReceiver = new InMemoryStatsReceiver
// loader helper
@Nullable
@throws[Exception]
protected def loader(key: Int): DataObject = { // this will replace to read the data from Redis Cache
new DataObject(s"LOADER_HELPER_$key")
}
def initCache(maximumSize: Int = 5): LoadingCache[Int, DataObject] = {
Caffeine
.newBuilder()
.maximumSize(maximumSize)
.refreshAfterWrite(defaultCacheExpireDuration.length, defaultCacheExpireDuration.unit)
.recordStats()
.build[Int, DataObject](key => loader(key))
.enableCacheStatsReporting("deal-service", stats)
}
}
我是 Scala 和 Caffeine 的新手,所以不确定我做错了什么;我尝试了 here and here 提到的不同方法来编写加载器,但没有任何效果(主要是在 Java 中)。对 Scala 边界的一些研究在这里没有任何帮助。请帮忙。
取决于这里使用的 Scala 版本。
尽管 Scala(2.12 及更高版本)函数支持转换为 Java SAM,但只有在明确需要时才会执行这些操作。所以如果你使用的是Scala 2.12或更高版本,你可以显式要求编译器将Scala函数转换为SAM,
此外,不要使用 Int
作为缓存的关键字。虽然它会因为隐式转换为 Integer
而起作用,但这不是一个好的做法。
def initCache(maximumSize: Int = 5): LoadingCache[Integer, DataObject] = {
Caffeine
.newBuilder()
.maximumSize(maximumSize)
.refreshAfterWrite(defaultCacheExpireDuration.length, defaultCacheExpireDuration.unit)
.recordStats()
.build[Integer, DataObject]((key => loader(key)): CacheLoader[Integer, DataObject])
.enableCacheStatsReporting("deal-service", stats)
}
如果您正在处理较旧的 Scala 版本,那么只需忘记 SAM 的存在并采用旧的方式即可。
def initCache(maximumSize: Int = 5): LoadingCache[Integer, DataObject] = {
Caffeine
.newBuilder()
.maximumSize(maximumSize)
.refreshAfterWrite(defaultCacheExpireDuration.length, defaultCacheExpireDuration.unit)
.recordStats()
.build[Int, DataObject](new CacheLoader[Integer, DataObject] {
override def load(key: Integer): DataObject = loader(key)
})
.enableCacheStatsReporting("deal-service", stats)
}
Scala 应用程序用例:
我们有一个基于 Scala 的模块从全局缓存 (Redis) 读取数据并将其保存到本地缓存 (Caffeine LoadingCache)。由于我们希望异步刷新此数据,因此我们使用 LoadingCache 并将 refreshAfterWrite 持续时间设置为刷新 window of 2.second.
问题: 不是问题,但需要以下代码的帮助,这些代码会发出警告和编译时错误
警告:对于build
方法,它给出警告为Implements member load in CacheLoader (com.github.benmanes.caffeine.cache)
编译时错误1: type arguments [Int,redisToCaffeine.DataObject] conform to the bounds of none of the overloaded alternatives of value build: [K1 <: Object, V1 <: Object](x: com.github.benmanes.caffeine.cache.CacheLoader[_ >: K1, V1])com.github.benmanes.caffeine.cache.LoadingCache[K1,V1] <and> [K1 <: Object, V1 <: Object]()com.github.benmanes.caffeine.cache.Cache[K1,V1] .build[Int, DataObject](key => loader(key))
编译时错误2: wrong number of type parameters for overloaded method value build with alternatives: [K1 <: Object, V1 <: Object](x: com.github.benmanes.caffeine.cache.CacheLoader[_ >: K1, V1])com.github.benmanes.caffeine.cache.LoadingCache[K1,V1] <and> [K1 <: Object, V1 <: Object]()com.github.benmanes.caffeine.cache.Cache[K1,V1] .build[Int, DataObject](key => loader(key))
代码:
package redisToCaffeine
import scala.concurrent.duration._
import com.github.benmanes.caffeine.cache.{ CacheLoader, Caffeine, LoadingCache }
import com.twitter.finagle.stats.InMemoryStatsReceiver
import javax.annotation.Nullable
import redisToCaffeine.CacheImplicits.StatsReportingCaffeineCache
class LocalDealService {
class DataObject(data: String) {
override def toString: String = {
"[ 'data': '" + this.data + "' ]"
}
}
val defaultCacheExpireDuration: FiniteDuration = 2.second
val stats: InMemoryStatsReceiver = new InMemoryStatsReceiver
// loader helper
@Nullable
@throws[Exception]
protected def loader(key: Int): DataObject = { // this will replace to read the data from Redis Cache
new DataObject(s"LOADER_HELPER_$key")
}
def initCache(maximumSize: Int = 5): LoadingCache[Int, DataObject] = {
Caffeine
.newBuilder()
.maximumSize(maximumSize)
.refreshAfterWrite(defaultCacheExpireDuration.length, defaultCacheExpireDuration.unit)
.recordStats()
.build[Int, DataObject](key => loader(key))
.enableCacheStatsReporting("deal-service", stats)
}
}
我是 Scala 和 Caffeine 的新手,所以不确定我做错了什么;我尝试了 here and here 提到的不同方法来编写加载器,但没有任何效果(主要是在 Java 中)。对 Scala 边界的一些研究在这里没有任何帮助。请帮忙。
取决于这里使用的 Scala 版本。
尽管 Scala(2.12 及更高版本)函数支持转换为 Java SAM,但只有在明确需要时才会执行这些操作。所以如果你使用的是Scala 2.12或更高版本,你可以显式要求编译器将Scala函数转换为SAM,
此外,不要使用 Int
作为缓存的关键字。虽然它会因为隐式转换为 Integer
而起作用,但这不是一个好的做法。
def initCache(maximumSize: Int = 5): LoadingCache[Integer, DataObject] = {
Caffeine
.newBuilder()
.maximumSize(maximumSize)
.refreshAfterWrite(defaultCacheExpireDuration.length, defaultCacheExpireDuration.unit)
.recordStats()
.build[Integer, DataObject]((key => loader(key)): CacheLoader[Integer, DataObject])
.enableCacheStatsReporting("deal-service", stats)
}
如果您正在处理较旧的 Scala 版本,那么只需忘记 SAM 的存在并采用旧的方式即可。
def initCache(maximumSize: Int = 5): LoadingCache[Integer, DataObject] = {
Caffeine
.newBuilder()
.maximumSize(maximumSize)
.refreshAfterWrite(defaultCacheExpireDuration.length, defaultCacheExpireDuration.unit)
.recordStats()
.build[Int, DataObject](new CacheLoader[Integer, DataObject] {
override def load(key: Integer): DataObject = loader(key)
})
.enableCacheStatsReporting("deal-service", stats)
}