代码之家  ›  专栏  ›  技术社区  ›  mdedetrich

使用运行时配置使参数化ScalaCache通用

  •  0
  • mdedetrich  · 技术社区  · 6 年前

    包含该问题的git repo可以在这里找到 https://github.com/mdedetrich/scalacache-example

    我目前的问题是,我试图使我的ScalaCache后端不可知,它可以在运行时使用typesafe配置进行配置。

    我遇到的问题是ScalaCache参数化了缓存的构造函数,也就是说,要构造一个咖啡因缓存

    ScalaCache(CaffeineCache())

    至于一个 SentinelRedisCache 你会的

    ScalaCache(SentinelRedisCache("", Set.empty, ""))

    MyCache 如下图所示

    import scalacache.ScalaCache
    import scalacache.serialization.Codec
    
    final case class MyCache[CacheRepr](scalaCache: ScalaCache[CacheRepr])(
      implicit stringCodec: Codec[Int, CacheRepr]) {
    
      def putInt(value: Int) = scalaCache.cache.put[Int]("my_int", value, None)
    }
    

    CacheRepr 因为ScalaCache知道如何序列化任何类型 T . CaffeineCache CacheRepr公司 哪个是 InMemoryRepr 哨兵雷迪斯卡切 CacheRepr公司 Array[Byte]

    这就是问题的症结所在,我有一个 Config

    import scalacache.Cache
    import scalacache.caffeine.CaffeineCache
    import scalacache.redis.SentinelRedisCache
    
    final case class ApplicationConfig(cache: Cache[_])
    

    原因是 Cache[_] ApplicationConfig 将在运行时使用 咖啡咖啡 / 哨兵雷迪斯卡切 .

    这就是问题的症结所在,Scala无法找到一个隐式的 Codec 对于通配符类型,如果我们只是 applicationConfig.cache 作为构造器,即。 https://github.com/mdedetrich/scalacache-example/blob/master/src/main/scala/Main.scala#L17

    [error] /Users/mdedetrich/github/scalacache-example/src/main/scala/Main.scala:17:37: Could not find any Codecs for type Int and _$1. Please provide one or import scalacache._
    [error] Error occurred in an application involving default arguments.
    [error]   val myCache3: MyCache[_] = MyCache(ScalaCache(applicationConfig.cache)) // This doesn't
    

    应用程序配置 ,缓存的类型为 Cache[InMemoryRepr | Array[Byte]] 缓存[\ux] (这样Scala编译器就知道如何查找 InMemoryRepr or Array[Byte] 我的缓存 被定义成这样

    final case class MyCache[CacheRepr <: InMemoryRepr | Array[Byte]](scalaCache: ScalaCache[CacheRepr])
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Tim    6 年前

    您似乎要求编译器根据运行时选择的缓存类型解析隐式值。这是不可能的,因为编译器在应用程序代码启动时不再运行。

    trait 表示缓存的抽象接口,并提供一个工厂函数,该函数基于中的设置返回特定实例 ApplicationConfig . 它可能看起来像这样(未经测试):

    sealed trait MyScalaCache {
      def putInt(value: Int)
    }
    
    object MyScalaCache {
      def apply(): MyScalaCache =
        if (ApplicationConfig.useCaffine) {
          MyCache(ScalaCache(CaffeineCache())
        } else {
          MyCache(ScalaCache(SentinelRedisCache("", Set.empty, ""))
        }
    }
    
    final case class MyCache[CacheRepr](scalaCache: ScalaCache[CacheRepr]) extends MyScalaCache (
      implicit stringCodec: Codec[Int, CacheRepr]) {
    
      def putInt(value: Int) = scalaCache.cache.put[Int]("my_int", value, None)
    }
    

    编译器将解析 MyCache 在编译时,其中在 apply .

    推荐文章