-
Notifications
You must be signed in to change notification settings - Fork 50
Open
Description
I've found that this piece of code prints "message" twice:
object Main extends App {
object StringByString extends Data[String, String] {
type StringByString[F[_]] = DataSource[F, String, String]
def name: String = "stringByString"
def source[F[_]: Concurrent]: StringByString[F] = new StringByString[F] {
override def CF: Concurrent[F] = Concurrent[F]
override def data: Data[String, String] = StringByString
override def fetch(accountId: String): F[Option[String]] =
Option(accountId).pure[F]
}
}
val ds = StringByString.source[IO]
val f = Fetch.optional(
"string", ds
).product(Fetch.liftF(IO(println("message"))))
println(Fetch.run(f).unsafeRunSync())
}
When a BlockedRequest is followed by Fetch.liftF, interpreter will execute that effect twice.
It is not very pleasant for us because in that Fetch.liftF we do a bunch of computational efforts and duplicating these computations might be quite wasteful.
Possible solution:
The problem I guess is in that piece of code:
override def product[A, B](fa: Fetch[F, A], fb: Fetch[F, B]): Fetch[F, (A, B)] =
Unfetch[F, (A, B)](for {
fab <- (fa.run, fb.run).tupled
result = fab match {
case (Throw(e), _) =>
Throw[F, (A, B)](e)
case (Done(a), Done(b)) =>
Done[F, (A, B)]((a, b))
case (Done(a), Blocked(br, c)) =>
Blocked[F, (A, B)](br, product(fa, c))
case (Blocked(br, c), Done(b)) =>
Blocked[F, (A, B)](br, product(c, fb))
case (Blocked(br, c), Blocked(br2, c2)) =>
Blocked[F, (A, B)](combineRequestMaps(br, br2), product(c, c2))
case (_, Throw(e)) =>
Throw[F, (A, B)](e)
}
} yield result)
Here we execute fb (which is Fetch.liftF) twice:
- (fa.run, fb.run).tupled
- product(c, fb)
We could reuse the result of fb by replacing product(c, fb)
to c.map((_, b))
Metadata
Metadata
Assignees
Labels
No labels