47erbot on cats-effect-3.3.13
47erbot on main
Update cats-effect to 3.3.13 (compare)
47erbot on cats-effect-3.3.13
Update cats-effect to 3.3.13 (compare)
47erbot on main
Update sbt-scalajs, scalajs-com… (compare)
47erbot on sbt-scalajs-1.10.1
47erbot on http4s-circe-0.23.13
47erbot on main
Update http4s-circe to 0.23.13 (compare)
47erbot on sbt-scalajs-1.10.0
47erbot on sbt-scalajs-1.10.1
Update sbt-scalajs, scalajs-com… (compare)
47erbot on http4s-circe-0.23.13
Update http4s-circe to 0.23.13 (compare)
47erbot on scala3-library-3.1.3
47erbot on main
Update scala3-library to 3.1.3 (compare)
ctx
and p
there be themselves implicits and you only provide those there. This is similar to what play framework does with { implicit request =>
If I have one single data source (think of a document db that stores JSON documents). Then the data source can be like:
implict object JsonStore extends DataSource[String, JSON]{
def name: String = ???
def fetchOne(id: Identity): Query[Option[Result]] = ???
def fetchMany(ids: NonEmptyList[Identity]): Query[Map[Identity, Result]] = ???
}
Now, we store more than one kinds of document there. Says, User and Post. We also have UserId
and PostId
that basically wrap a String
and enforce certain format for each ids. And UserModel
and PostModel
are case classes that could be serialized to JSON. What is the right way to have two data sources that return both data types and can batch and cache results for both?
Thanks
Hi,
Playing with introduction code http://47deg.github.io/fetch/docs.html#introduction-0
for {
x: User <- getUser(1)
} yield s"${x.id} ${x.username}”
Produces following error:Error:(105, 23) value filter is not a member of fetch.Fetch[User]
Thoughts on how to get around this?
withFilter
?
(fetchA,fetchB).tupled
even if the two fetches ultimately execute in parallel, I have to wait until they both complete to get the full tuple.
F[(F[A],F[B])]
or something like that.
I could wait until I have everything and then send to my UI, but I'd like to send some data from the first round of calls, render what I can, and then send subsequent data.
the use case makes sense, although I'm not sure Fetch could support that at the moment. I've been talking with a colleague about how we could support it but I need to spend some more cycles on it to have an answer
thanks, I just wanted to be clear it wasn't a memory/infinite stream thing I was asking for. Thinking out loud: How about attaching an IO action/callback to a Fetch. Something like:
def subFlatMap[A, B](fa: Fetch[F, A])(f: A => F[B]): Fetch[F, B] = Unfetch(fa.run.flatMap {
case Done(v) => f(v).map(Done(_))
case Throw(e) =>
Applicative[F].pure(Throw[F, B](e))
case Blocked(br, cont) =>
Applicative[F].pure(Blocked(br, subFlatMap(cont)(f)))
})
Then you could do:
```
def sendToClientA: F[A] = for {
_ <- sendData(a)
} yield a
def sendDataA: F[Unit] = ???
Fetch
es, I can only flatMap
or traverse
, i.e. there is only support for the happy path, so all Fetch
es succeed or one fails and then all fail. However, I have in some cases appropriate business logic what to do if it's not there or would even return the user an empty result. The only way I see of doing this is to do bring it back to the IO
context and handle the error there with something like Fetch.run(myFetch).attempt
. But then I would like to get back to the Fetch[IO, _]
monad so it plays together with all the other requests that have to be composed together on the higher level
private def fetchOrNone(f: Fetch[IO, ExternalId])(
implicit C: cats.effect.ConcurrentEffect[IO],
CS: cats.effect.ContextShift[IO],
T: cats.effect.Timer[IO]
): Fetch[IO, Option[ExternalId]] =
Unfetch[IO, Option[ExternalId]](
Fetch
.run(f)
.map(Some(_))
.handleError(_ => None[ExternalId])
.map(Done(_))
)
.tupled
on a pair of Fetch[F, Foo]
instances:scala> def fetchProduct[F[_] : ConcurrentEffect]: Fetch[F, (User, User)] =
| (getUser(1), getUser(2)).tupled
<console>:200: error: value tupled is not a member of (fetch.Fetch[F,User], fetch.Fetch[F,User])
(getUser(1), getUser(2)).tupled
^
cats.effect.IO
throughout rather than more generic cats effect typeclasses. can i just fix type FetchIO[T] = Fetch[IO, T]
(not sure if that's actually proper syntax for higher kinded programming in scala) and use FetchIO
instead of Fetch
throughout? we may generalize down the line, but looking for a quicker win first.
.tupled
, make sure you import the Applicative syntax cats.syntax.applicative._
so you can use it, see https://github.com/typelevel/cats/blob/master/docs/src/main/tut/typeclasses/applicative.md#syntax
IO
type, you can just do type FetchIO[A] = Fetch[IO, A]
as you mentioned :+1:
Fetch
instances using Fetch#optional
. It will yield a Fetch[F, Option[A]]
, and won't fail if the identity is missing. Let me know if it helps!
@purrgrammer
scala> import cats.syntax.applicative._
import cats.syntax.applicative._
scala> def fetchProduct[F[_] : ConcurrentEffect]: Fetch[F, (User, User)] =
| (getUser(1), getUser(2)).tupled
<console>:181: error: value tupled is not a member of (fetch.Fetch[F,User], fetch.Fetch[F,User])
(getUser(1), getUser(2)).tupled
^
after copy-pasting everything in http://47deg.github.io/fetch/docs.html#syntax-6-companion-object-0 up to the def getUser
IO[T]
to a Fetch[IO, T]
without defining a Data/DataSource for it? i have certain code that’s un-batchable anyway and it would make a lot of my code more straightforward if i could just lift it right into Fetch
.
def liftT[T](io: IO[T]): Fetch[IO, T] = {
object Lift extends Data[IO[T], T] {
val name = "Lifts an IO[T] to a Fetch[IO, T]"
def source: DataSource[IO, IO[T], T] = new DataSource[IO, IO[T], T] {
override def data = Lift
override def CF: ConcurrentEffect[IO] = ConcurrentEffect[IO]
override def fetch(id: IO[T]): IO[Option[T]] = (
id.map(Some(_))
)
}
}
Fetch(io, Lift.source)
}
is there any way to lift an
IO[T]
to aFetch[IO, T]
without defining a Data/DataSource for it? i have certain code that’s un-batchable anyway and it would make a lot of my code more straightforward if i could just lift it right intoFetch
.
that's something that I hadn't thought about, right now Fetch assumes you'll use a Data/DataSource for performing requests. If i understood correctly, you want a way to lift IO actions to Fetch without an associated Data/DataSource, knowing that those requests can't be optimized?