scala - F多态代码中如何使用guave缓存加载器
问题描述
我有一项服务,它 从官方示例中返回笑话:
final case class JokeError(e: Throwable) extends RuntimeException
def impl[F[_] : Sync](C: Client[F]): Jokes[F] = new Jokes[F] {
val dsl = new Http4sClientDsl[F] {}
import dsl._
def get: F[Jokes.Joke] = {
C.expect[Joke](GET(uri"https://icanhazdadjoke.com/"))
.adaptError { case t => JokeError(t) }
}
}
但我想用番石榴缓存缓存第一个请求的笑话(只是通过常量键,这没关系):
object Jokes {
def apply[F[_]](implicit ev: Jokes[F]): Jokes[F] = ev
final case class Joke(joke: String) extends AnyRef
object Joke {
implicit val jokeDecoder: Decoder[Joke] = deriveDecoder[Joke]
implicit def jokeEntityDecoder[F[_]: Sync]: EntityDecoder[F, Joke] =
jsonOf
implicit val jokeEncoder: Encoder[Joke] = deriveEncoder[Joke]
implicit def jokeEntityEncoder[F[_]: Applicative]: EntityEncoder[F, Joke] =
jsonEncoderOf
}
final case class JokeError(e: Throwable) extends RuntimeException
def impl[F[_]: Sync](C: Client[F]): Jokes[F] = new Jokes[F]{
val cacheLoader : CacheLoader[String, Joke] = new CacheLoader[String, Joke] {
override def load(key: String): Joke = {
import dsl._
val joke: F[Joke] = C.expect[Joke](GET(uri"https://icanhazdadjoke.com/"))
.adaptError{ case t => JokeError(t)}
//? F[Joke] => Joke
null
}
}
val cache = CacheBuilder.newBuilder().build(cacheLoader)
val dsl = new Http4sClientDsl[F]{}
def get: F[Jokes.Joke] = {
//it's ok?
cache.get("constant").pure[F]
}
}
}
如您所见,cacheLoader
需要“物化”值F[Joke] => Joke
。并且缓存返回纯值而不F
如何在F
多态代码中使用此缓存?
解决方案
您基本上是在询问如何在 中运行多态代码F
,为此您需要Effect
对F
.
此外pure
,您需要使用而不是使用delay
,因为从缓存中获取值是一种副作用。
val cacheLoader : CacheLoader[String, Joke] = new CacheLoader[String, Joke] {
override def load(key: String): Joke = {
import dsl._
val joke: F[Joke] = C.expect[Joke](GET(uri"https://icanhazdadjoke.com/"))
.adaptError{ case t => JokeError(t)}
// This is a side effect, but can't avoid it due to the way the API is designed
joke.toIO.unsafeRunSync()
}
}
val cache = CacheBuilder.newBuilder().build(cacheLoader)
val dsl = new Http4sClientDsl[F]{}
def get: F[Jokes.Joke] = {
// This is okay :)
Sync[F].delay(cache.get("constant"))
}
顺便说一句,如果你想使用与 http4s 互操作性非常好的东西,我强烈推荐mules
. 在这里查看:
https ://github.com/ChristopherDavenport/mules
推荐阅读
- java - 以正确的方式操作数据模型
- javascript - 我不明白如何将 findOrCreate 方法与猫鼬一起使用
- android - 如何从打开的街道地图中删除自定义标记并重新加载?
- mysql - Mysql查询多列上的多个select语句输出
- node.js - 使用 zeit 的 pkg 打包 typescript 应用程序(找不到 lib.d.ts)
- css - SVG 变形与anime.js
- python - Python:E1136:Value 'self.exchange.get_portfolio' 不可订阅
- node.js - 调用 https 请求以对 Stripe API 收费时出现错误 400
- python-3.x - 如何从列表中删除特定随机选择的元素?
- excel - 同一主题的平均多个分数