在桑格利亚汽酒中将多个延迟值合并为新的延迟类型GraphQL实现

时间:2018-07-26 08:35:21

标签: scala graphql sangria

我们有两个端点(后端调用),它们返回不同但相关的数据类型XDataYData。如果存在XData实例,其ID为1,则必须存在一个YData实例,其ID为1

我们为每种数据类型xFetcheryFetcher创建了一个访存器。这些提取程序在GraphQL查询中分别用于从两个端点获取数据,但是对于某些用例,我们希望使用特定的ID(例如,1)组合从两个端点检索到的数据。如下例所示,这种组合可能不是简单的列表追加。

由于在查询的其他部分也分别查询了XDataYData,因此我们不能简单地将这两个解析器合并为一个,并且如果出现以下情况,我们将尝试避免对同一端点进行多次调用可能。

我为此用例创建了一个简化示例。我们如何返回一个从两个提取程序中获取的数据相结合的递延值?

case class Ctx()
case class XData(id: Int, a: Seq[String], b: String)
case class YData(id: Int, a: Seq[String], c: String)
case class Data(id: Int)

val xFetcher = Fetcher((ctx: Ctx, ids: Seq[Int]) => Future {
  ids.map(id => XData(1, Seq.empty, "")) // Back end call to (endpoint X)
})(HasId(_.id))

val yFetcher = Fetcher((ctx: Ctx, ids: Seq[Int]) => Future {
  ids.map(id => YData(1, Seq.empty, "")) // Back end call to (endpoint Y)
})(HasId(_.id))

val GData = deriveObjectType[Ctx, Data](
  AddFields(
    Field("a",
      ListType(StringType),
      resolve = ctx => getA(ctx))
  )
)

def getA(ctx: Context[Ctx, Data]) = {
  val id = ctx.value.id

  // Here I should also get an instance of `YData` and return the
  // combination of the sequences `a` in both instances (xData, yData)
  val xData: XData = ??? //getDeferredXData()
  val yData: YData = ??? //getDeferredYData()
  val desiredOutput = xData.a ++ yData.a

  // I can get `a` from one instance but not both of them together
  DeferredValue({
    val xData = xFetcher.defer(id)
    // val yData = yFetcher.defer(id)
    // How can we combine both into one deferred value?
    xData
  }).mapWithErrors { data => (data.a, Vector.empty) }
}

我没用过桑格利亚汽酒,所以请原谅与deferred resolversfetchers相关的任何不清楚的信息

1 个答案:

答案 0 :(得分:1)

您的方案的描述听起来很类似于此问题:

Add additional items to per-request cache

它已经实现,但尚未发布。

此外,如果可以总是一起加载XDataYData,那么可以为元组(XData, YData)定义访存程序。然后,在解析器中,您可以从元组中提取所需的对象。像这样:

DeferredValue(fetcher.defer(id)).map {case (xData, yData) ⇒ xData}