У нас есть две конечные точки (внутренние вызовы), которые возвращают разные, но релевантные типы данных 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.





Описание вашего сценария очень похоже на эту проблему:
Добавить дополнительные элементы в кеш по запросу
Он уже реализован, но еще не выпущен.
Кроме того, если можно всегда загружать XData и YData вместе, вы можете определить сборщик для кортежа (XData, YData). Затем в преобразователе вы можете извлечь нужный объект из кортежа. Что-то вроде этого:
DeferredValue(fetcher.defer(id)).map {case (xData, yData) ⇒ xData}
Спасибо за новую функцию и за ваш ответ. Я думаю, может помочь, если мы кэшируем
XDataпри первом запросе, а затем обращаемся к этому кешу, когда нам нуженYData.YDataв нашем случае - это расширенные данные, к которым осуществляется доступ при необходимости, и эти данные извлекаются не только из одной службы, но и еще примерно из 5.XDataочень большой и всегда возвращается, поэтому важно использовать его сборщик, чтобы уменьшить количество обращений к сервисуXDataпри запросе расширенного. Если вы считаете, что мне нужно уточнить детали и создать новый выпуск, сообщите мне.