Какой должна быть схема отношений между микросервисами

Я использую NestJS + Prisma + Apollo Federation.

В микросервисе A есть определение пользователя, в микросервисе B - сообщения. Отношение 1 - N, у пользователя может быть N сообщений.

В Prisma модель данных Post определяется строкой для пользователя, поскольку userId - это uuid.

type Post {
  id: Int! @id
  createdAt: DateTime! @createdAt
  updatedAt: DateTime! @updatedAt
  user: String!
}

В сгенерированной схеме (с https://graphql-code-generator.com/) Post имеет атрибут типа User, и этот тип User расширяет идентификатор и массив сообщений:

type Post @key(fields: "id") {
  id: Int!
  createdAt: DateTime!
  updatedAt: DateTime!
  user: User!
}

extend type User @key(fields: "id") {
  id: ID! @external
  posts: [Post]
}

В федерации apollo все работает, как ожидалось, за исключением случаев, когда делается запрос на установление связи между обоими микросервисами.

На игровой площадке, если вы попытаетесь запросить сообщения с его пользователем без установки подполей, это нарушит схему и скажет, что вы должны установить подполя пользователя, и если вы установите подполя, graphql ответит сообщением, что вы не можете использовать подполя, потому что его тип это строка.

Единственный способ, которым я мог сделать это правильно, - это установить в Prisma поле userId типа string и установить другое поле в схеме с именем user типа User. Но во всех примерах не было поля для работы с db и поля для работы со схемой.

Мой вопрос: рекомендуется ли это или я что-то упускаю.

1 ответ

Чтобы получить User от Post, вам необходимо создать преобразователь в своем посте и пользовательском сервисе.

Почтовая служба

const resolvers = {
  Post:{//before you do this you have to extend User schema which you already did.
      // you are basically asking the 'User' service, which field should be used to query user.
    user: ref => ({ __typename: 'User', id: ref.userId })
  }
  Query:{
    // query resolvers
  },
  Mutation:{
    // mutation resolvers
  }

Пользовательское обслуживание

const resolvers = {
  User:{//the code below allows other services to extend User in their own schemas
    __resolveReference: (ref, { userDataLoader }) => userDataLoader.load(ref.id),
  }
  Query:{
    // query resolvers
  },
  Mutation:{
    // mutation resolvers
  }

Теперь связываем такие массивы, как [Post] должно быть сделано исключительно на почте

Почтовая служба

const resolvers = {
  Post:{//before you do this you have to extend User schema which you already did.
      // you are basically telling the user service, which field should be used to query user.
    user: ref => ({ __typename: 'User', id: ref.user })
  },
  User:{
    posts:(ref, args, {postDataLoader}) => getOrders(ref.postIds) //or ref.userId(foreign key)
  },
  Query:{
    // query resolvers
  },
  Mutation:{
    // mutation resolvers
  }
Другие вопросы по тегам