sangria icon indicating copy to clipboard operation
sangria copied to clipboard

Fetcher creation function / stateful fetcher

Open fokot opened this issue 5 years ago • 1 comments

More times I came to situation when I needed to do fetcher with some context. But all fetchers needs to be sent to Executor.execute which I do not know ahead of time

def fetcherForQuery(query: String): Fetcher[AllAppContext, FoundByType, FoundByType, ID] = Fetcher(
  (ctx: AllAppContext, ids: Seq[ID]) => ctx.service.foundBy(ids, query)
)

I can implement it also this way or running find by for every query found in ids..

val FetcherForQuery: Fetcher[AllAppContext, FoundByType, FoundByType, (ID, String)] = Fetcher(
  (ctx: AllAppContext, ids: Seq[(ID, String])) => {
    if(ids.map(_._2).distinct.leght != 1)
      Future.failed(new Exception("There is not easy way to write single fetch for multiple queries"))
    else
      ctx.service.foundBy(ids.map(_._1), ids.head._2)
  }
)

Is there a way how to do it now nicely in Sangria? Maybe using DeferredResolver instead of Fetcher but I couldn't find good explanation in docs how to use DeferredResolver.

fokot avatar Dec 17 '18 13:12 fokot

Hi, @fokot, long time! .

There is an old article about DeferredResolver : https://medium.com/@toxicafunk/graphql-subqueries-with-sangria-735b13b0cfff maybe it will help you.

Also, not sure I understand a problem correctly, but maybe pushing a logic down the hill would help you to catch it and add some additional logic. in Scala turorial (https://www.howtographql.com/graphql-scala/7-relations/) you can see that one of the fetchers is defiened in generic way:

(ctx: MyContext, ids: RelationIds[Vote]) => ctx.dao.getVotesByRelationIds(ids)

and it's possible to use additional logic on database level, like this:

def getVotesByRelationIds(rel: RelationIds[Vote]): Future[Seq[Vote]] =
 db.run(
   Votes.filter { vote =>
     rel.rawIds.collect({
       case (SimpleRelation("byUser"), ids: Seq[Int]) => vote.userId inSet ids
       case (SimpleRelation("byLink"), ids: Seq[Int]) => vote.linkId inSet ids
     }).foldLeft(true: Rep[Boolean])(_ || _)

   } result
 )

Hope it'd help.. In case of more specific questions...

marioosh avatar Dec 17 '18 16:12 marioosh