Last active
June 16, 2022 21:04
-
-
Save horothesun/1036fb618a6f135a58c501aa94338e8d to your computer and use it in GitHub Desktop.
Cats-effect - Cached client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cats.effect.{IO, Resource} | |
case class Config() | |
case class InputA() | |
case class InputB() | |
case class InputC() | |
case class OutputA() | |
case class OutputB() | |
case class OutputC() | |
trait Client { | |
def getDataA(input: InputA): IO[OutputA] | |
def getDataB(input: InputB): IO[OutputB] | |
def getDataC(input: InputC): IO[OutputC] | |
} | |
/* | |
Default instance: Client.createDefault(config) | |
Cached instance: Client.cached(Client.createDefault(config)) | |
*/ | |
object Client { | |
def createDefault(config: Config): Resource[IO, Client] = ??? | |
def cached(base: Resource[IO, Client]): Resource[IO, Client] = | |
base.evalMap(baseClient => | |
( | |
IO.ref[Map[InputA, OutputA]](Map.empty), | |
IO.ref[Map[InputB, OutputB]](Map.empty), | |
IO.ref[Map[InputC, OutputC]](Map.empty) | |
).tupled | |
.map { case (outputACache, outputBCache, outputCCache) => | |
new Client { | |
override def getDataA(input: InputA): IO[OutputA] = | |
cached(baseClient.getDataA, input, outputACache) | |
override def getDataB(input: InputB): IO[OutputB] = | |
cached(baseClient.getDataB, input, outputBCache) | |
override def getDataC(input: InputC): IO[OutputC] = | |
cached(baseClient.getDataC, input, outputCCache) | |
} | |
} | |
) | |
private def cached[Input, Output]( | |
methodToCache: Input => IO[Output], | |
input: Input, | |
cacheRef: Ref[IO, Map[Input, Output]] | |
): IO[Output] = | |
cacheRef.get | |
.flatMap { cache => | |
val ifCacheIsEmpty = | |
methodToCache(input) | |
.flatMap(output => | |
cacheRef | |
.update(oldCache => oldCache + (input -> output)) | |
.as(output) | |
) | |
cache.get(input).fold(ifCacheIsEmpty)(IO.pure) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment