在Apollo Federation中执行实体所有权
在Apollo Federation 2中指定实体所有权
Federation 2中,“扩展”一个实体类型的概念是严格的。所有不同子图中对类型的定义都根据字段的可共享性进行合并。在下面的示例中,没有任何子图真正拥有或扩展了Product
实体。相反,它们都为其贡献了字段。
type Product @key(fields: "id") {id: ID!name: String}
type Product @key(fields: "id") {id: ID!reviews: [Review]}
联邦1要求其中一个定义使用了 extend
关键字或 @extends
指令。联邦2取消这项要求以提高 组合 的灵活性并减少硬组合错误的可能。
然而,在某些情况下,您仍然可能想指定一个 实体 的 “所有者” 并使 “实体扩展” 成为 超级图 中的第一类概念。
一个例子是断言哪个 子图 负责记录一个 实体。如果两个子图向一个类型添加不同的描述, 组合 选择其中一个描述并向您发出不一致的提示:
HINT: [INCONSISTENT_DESCRIPTION]: Element "Product" has inconsistentdescriptions across subgraphs. The supergraph will use description(from subgraph "one"):"""The Product type lorem ipsum dolar sit amet."""In subgraph "two", the description is:"""This is my description of the Product type."""
ⓘ 注意
当描述在 子图 中不一致时, 组合 将根据名称按字母顺序从第一个子图中选择描述。
决定类型的 “所有者” 的机制允许工具(如代码审查工具)在开发过程中较早捕获这些不一致。
创建 @owner
指令
您可以使用 Federation 2.2 中引入的 @composeDirective
功能将 @owner
指令添加到您的 supergraph。
extend schema@link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key", "@composeDirective"])@link(url: "https://graphql.mycompany.dev/owner/v1.0", import: ["@owner"])@composeDirective(name: "@owner")directive @owner(team: String!) on OBJECTtype Product @key(fields: "id") @owner(team: "subgraph-a") {id: ID!name: String}
现在 @owner
指令出现在了 超图 中。因为我们没有将指令定义为 可重复的
, 子图 无法使用不同的 参数 定义它。
使用 @owner
指令编写 lint 规则
以下是使用 @graphql-eslint
规则的例子,该规则用于 子图模式,并且使用 @owner
指令来确定是否需要一个描述:
使用 @owner
确定所需审批者
对于 @owner
指令的另一个用例是在模式更改影响另一个团队拥有的类型时,确定所需的审查者。
具体过程取决于您的源代码控制和持续集成系统。以下示例步骤假设您同时使用 GitHub。
添加一个
pull_request
工作流程:.github/workflows/add-reviewers.yamlname: Add required reviewers for owned GraphQL typeson: [pull_request]确定方案更改影响的类型
import { diff } from "@graphql-inspector/core";import { buildSchema } from "graphql";const differences = diff(buildSchema(schemaFromBaseRef, { assumeValidSDL: false }),buildSchema(schemaFromCurrentRef, { assumeValidSDL: false }));/* Derive a list of affected types from the result:[{"criticality": {"level": "NON_BREAKING"},"type": "FIELD_ADDED","message": "Field 'newField' was added to object type 'Product'","path": "Product.newField"}]*/获取 超图模式。
您可以使用
rover supergraph fetch
或使用 Apollo Platform API.提取受影响类型的所有者
import { getDirective } from "@graphql-tools/utils";const supergraphSchema = buildSchema(supergraphSdl);const affectedTeams = [];for (const typeName of affectedTypes) {const type = supergraphSchema.getType(typeName);const owner = getDirective(schema, type, "owner")?.[0];if (owner) {affectedTeams.push(owner.team);}}将团队添加为拉取请求的审阅者
import { Octokit } from "@octokit/action";const octokit = new Octokit();const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");await octokit.pulls.requestReviewers({owner,repo,pull_number: pullNumber, // ${{ github.event.number }}team_reviewers: affectedTeams,});