Объединение нескольких отложенных значений в новый отложенный тип в Sangria, реализация GraphQL

У нас есть две конечные точки (внутренние вызовы), которые возвращают разные, но соответствующие типы данных XData а также YData, Если экземпляр XData существует с идентификатором 1то должен быть экземпляр YData с тем же идентификатором 1,

Мы создали сборщик для каждого типа данных xFetcher а также yFetcher, Эти средства извлечения используются отдельно в нашем запросе GraphQL для извлечения данных с обеих конечных точек, но для некоторых случаев использования мы хотим объединить данные, извлеченные из них обоих, используя определенный идентификатор, например, 1, Эта комбинация может быть не простым добавлением в список, как показано в примере ниже.

Как XData а также YData запрашиваются также отдельно в других частях запроса, мы не можем просто объединить эти два резольвера в один, и мы стараемся по возможности избежать нескольких вызовов к одной и той же конечной точке.

Я создал упрощенный пример для этого варианта использования. Как мы можем вернуть одно отложенное значение, объединяющее данные, полученные из двух сборщиков?

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 resolvers или же fetchers

1 ответ

Описание вашего сценария звучит очень похоже на эту проблему:

Добавить дополнительные элементы в кеш запроса

Он уже реализован, но еще не выпущен.

Кроме того, если это нормально, чтобы всегда загружать XData а также YData вместе, тогда вы можете определить сборщик для кортежа (XData, YData), Затем в резольвере вы можете извлечь нужный объект из кортежа. Что-то вроде этого:

DeferredValue(fetcher.defer(id)).map {case (xData, yData) ⇒ xData}
Другие вопросы по тегам