AWS AppSync

AWS AppSync,简称 GraphQL 的 API 网关,因为它允许您将 GraphQL 架构连接到不同的数据源,如 RDS、DynamoDB、Lambda、HTTP 端点等。

我们在 Purple 应用程序中使用 AppSync 来支持应用程序 API。

在Purple Stack API 文档中了解更多信息。

AppSync 订阅

首先,我们很高兴看到 AppSync 支持 GraphQL 订阅。但是当我们发现它们与突变紧密结合时,兴奋度略有下降。

在一些超级简单的 CRUD 系统上工作时,这个特性似乎很好,但是当你开始构建一个更大的应用程序时,它有很多业务逻辑隐藏在像 Step Functions 这样的异步后台进程中,它开始出现不足。

我们通过使用传递 lambda 解析器创建虚拟突变来解决该问题,该解析器只能由 IAM 用户](https://docs.aws.amazon.com/appsync/latest/devguide/security.html#aws-iam-authorization)调用[。

后来我们发现了“local resolvers”,它可以完成同样的工作而无需调用 lambda 函数。

在此过程中,我们偶然发现了一些特定的 AppSync 行为,这些行为乍一看并不明显,并且有关它们的信息被“隐藏”在文档深处复杂的句子中。

经验教训

1\。订阅参数与突变响应字段匹配,而不是与突变参数匹配。

文档中没有任何地方说明与魔术匹配的订阅参数究竟是如何工作的。目前尚不清楚匹配是针对突变参数还是突变响应字段进行的。

type Mutation {
  addItem(argA: ID!, argB: String!, argC: Int!): AddItemResponse!
}

type Subscription {
  # filtering by "argA" ❌
  onAddItem(argA: ID!): AddItemResponse 
  @aws_subscribe(mutations: ["addItem"])

  # filtering by "fieldF" ✅
  onAddItem(fieldF: String!): AddItemResponse 
  @aws_subscribe(mutations: ["addItem"])

}

type AddItemResponse {
  fieldD: String!
  fieldE: Int!
  fieldF: String!
}

进入全屏模式 退出全屏模式

2\。订阅响应必须是可选的

我不明白为什么,但订阅响应必须是可选的。 AppSync 允许您使用所需的订阅响应成功保存架构,但是当您尝试从前端客户端连接到订阅时,它开始抛出一些浅薄的错误,该错误并未明确告诉您订阅响应必须是可选的。然后你花了几个小时试图找出问题出在哪里。

type Mutation {
  addItem(argA: ID!, argB: String!, argC: Int!): AddItemResponse!
}

type Subscription {
  # AddItemResponse is optinal  ✅
  onAddItem(fieldF: String!): AddItemResponse 
  @aws_subscribe(mutations: ["addItem"])

  # AddItemResponse is required ❌
  onAddItem(fieldF: String!): AddItemResponse! 
  @aws_subscribe(mutations: ["addItem"])

}

type AddItemResponse {
  fieldD: String!
  fieldE: Int!
  fieldF: String!
}

进入全屏模式 退出全屏模式

3\。订阅消息仅包含突变请求的字段 - 其他字段将为空

一段时间后,我发现这在文档的三个大段落中得到了解释。

关键是,即使您的 lambda 解析器正在返回所有突变字段的值,AppSync 订阅也只会看到在突变请求中选择的突变字段。这可能是因为解析器不必为突变请求中未请求的字段返回值。

GraphQL 架构
type Mutation {
  addItem(argA: ID!, argB: String!, argC: Int!): AddItemResponse!
}

type Subscription {
  onAddItem(fieldA: String!): AddItemResponse 
  @aws_subscribe(mutations: ["addItem"])
}

type AddItemResponse {
  fieldA: String!
  fieldB: Int!
  fieldC: String!
}

进入全屏模式 退出全屏模式

在某些异步进程中在后端调用突变
mutation AddItem {
  addItem(argA: "valueA", argB: "valueB", argC: 123) {
    fieldA
    fieldC
  }
}

进入全屏模式 退出全屏模式

前端订阅声明
subscription SubscribeOnAddItem {
  onAddItem(fieldA: "valueA") {
    fieldA
    fieldB
    fieldC
  }
}

进入全屏模式 退出全屏模式

生成的订阅消息
{
  fieldA: 'valueA', 
  fieldB: null, // fieldB is null because it was not requested in the mutation
  fieldC: 123
}

进入全屏模式 退出全屏模式

4\。如果突变响应中未指定过滤字段,则不会触发订阅

这个特性可以从第一点推断出来,但它仍然是一个重要的实现。

GraphQL 架构
type Mutation {
  addItem(argA: ID!, argB: String!, argC: Int!): AddItemResponse!
}

type Subscription {
  onAddItem(fieldA: String!): AddItemResponse 
  @aws_subscribe(mutations: ["addItem"])
}

type AddItemResponse {
  fieldA: String!
  fieldB: Int!
  fieldC: String!
}

进入全屏模式 退出全屏模式

在某些异步进程中在后端调用突变
mutation AddItem {
  addItem(argA: "valueA", argB: "valueB", argC: 123) {
    fieldB
    fieldC
  }
}

进入全屏模式 退出全屏模式

前端订阅声明
subscription SubscribeOnAddItem {
  onAddItem(fieldA: "valueA") {
    fieldA
    fieldB
    fieldC
  }
}

进入全屏模式 退出全屏模式

在这种情况下,订阅不会被触发,因为突变没有请求用于过滤订阅数据的fieldA

即使您的 lambda 解析器也返回了fieldA的值,但它不会起作用,因为匹配发生在选择请求的字段之后 - 而不是之前。

5\。订阅解析器是可选的 - 但它可用于授权

当我测试订阅时,我问自己,“如果我为订阅创建一个 lambda 解析器会发生什么?”所以我尝试了,我发现每次在建立新的订阅连接之前都会调用订阅解析器。

订阅解析器似乎是用于授权的,因为您作为解析器的输出返回什么并不重要。唯一重要的是解析器功能是成功还是失败。如果成功,则建立连接;如果失败,则会将错误发送到前端。

GraphQL 架构
type Mutation {
  addItem(owner: ID!, text: String!): AddItemResponse!
}

type Subscription {
  onAddItem(owner: String!): AddItemResponse 
  @aws_subscribe(mutations: ["addItem"])
}

type AddItemResponse {
  owner: String!
  text: String!
}

进入全屏模式 退出全屏模式

订阅解析器
'use strict'

module.exports.handler = async (event) => {
  if (event.identity.username === event.arguments.owner) {
    return {}
  }
  throw new Error('Access denied')
}

进入全屏模式 退出全屏模式

结论

AppSync 是一项不错且有用的服务,但它仍有一些改进空间和我们绝对期待的新功能。

希望这篇文章能让您的生活更轻松,以防您一直在为 AppSync 苦苦挣扎,并且您可以更好地了解可以用它做什么。

❤️ 在欧洲捷克共和国布尔诺制造。

如果您有任何问题,请随时通过 Twitter@FilipPyrek与我联系。

在Purple Technology 博客上查看我们的更多文章。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐