Федерация Apollo: поле / преобразователь, который возвращает объекты из двух отдельных служб, реализующих интерфейс.
Резюме
В управляемой федерации GraphQL Apollo я пытаюсь выяснить, возможно ли, чтобы одна служба имела агрегатное поле, которое возвращает массив объектов двух отдельных служб. То есть, я пытаюсь поддержать этот вариант использования:
query FromTwoServices {
aggregateField {
id
...on Service1Entity {
field1
}
...on Service2Entity {
field2
}
}
}
где оба
type Service1Entity implements Aggregation
а также
type Service2Entity implements Aggregation
А под капотом решатель для
aggregateField
(который живет в Сервисе 2) звонит в Сервис 1, чтобы
Service1Entity
с. Итак, это поле объединяет два набора данных.
Пример проблемы
В моей текущей настройке GraphQL все это определено в одной службе:
interface Animal {
id: ID!
name: String!
}
type Cat implements Animal {
id: ID!
name: String!
meows: Boolean
}
type Dog implements Animal {
id: ID!
name: String!
barks: Boolean
}
Когда я запрашиваю свой сервис, он попадает в распознаватель и выглядит так:
query Animals {
animals {
id
...on Cat {
meows
}
...on Dog {
barks
}
}
}
Сейчас создаю сервис. Я хотел бы прийти из службы собак, а кошек - из службы кошек. Кроме того, я все еще хотел бы поддерживать свое поле агрегации, и я хотел бы переместить его в
Dogs
услуга.
Чтобы поддержать это, я создал объект и продублировал интерфейс для обеих служб. Чтобы разрешить службе собак определять тип, я использовал " ссылку ", чтобы сообщить службе собак, что
Cat
живет где-то еще.
Cat Service (отметив Cat как объект с
@key
):
interface Animal {
id: ID!
name: String!
}
type Cat implements Animal @key(fields: "id") {
id: ID!
name: String!
meows: Boolean
}
Кинологическая служба:
interface Animal {
id: ID!
name: String!
}
type Cat implements Animal @key(fields: "id") {
id: ID! @external
}
type Dog implements Animal {
id: ID!
name: String!
barks: Boolean
}
Проблема с этой настройкой заключается в том, что служба Dog не запускается из-за этой ошибки GraphQL:
Ошибка: ожидается поле интерфейса Animal.name, но Cat его не предоставляет.
В моем сервисе для собак, если я добавлю внешний
name
поле, вот так:
type Cat implements Animal @key(fields: "id") {
id: ID! @external
name: String! @external
}
Затем две службы не могут объединиться в управляемую федерацию:
На этом графике данных отсутствует допустимая конфигурация. [dog] Cat.name -> помечено как @external, но не используется директивами @requires, @key или @provides.
Мне кажется, что я иду здесь по неправильному пути. Возможно ли иметь такое агрегированное поле, в котором одна служба может возвращать свои собственные сущности в сочетании с сущностями другой службы?
У нас уже есть много клиентов, запрашивающих
animals
поле, поэтому мы пытаемся поддержать это изменение, не требуя изменений клиента, иначе говоря, без реструктуризации использования интерфейса.