Федерация 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 поле, поэтому мы пытаемся поддержать это изменение, не требуя изменений клиента, иначе говоря, без реструктуризации использования интерфейса.

0 ответов

Другие вопросы по тегам