AWS AppSync 在解析子资源之前等待 DynamoDB Streams Lambda 函数

AWS AppSync wait for DynamoDB Streams Lambda function before resolving sub-resource

我有类似于以下的 GraphQL 架构。一个 Bravo 中有多个 Alpha,它们每个都相互引用。 (Bravo 可以得到它的 Alpha,Alpha 可以得到它的 Bravo。)

type Alpha {
  id: ID!
  value: Int!
  bravo: Bravo!
}

type Bravo {
  value: Int!
  alphas: [Alpha!]!
}

input InputAlpha {
  value: Int!
}

type Mutation {
  putAlpha(alpha: InputAlpha): Alpha!
}

schema {
  mutation: Mutation
}

如您所知,这两种类型都有一个值。 Alpha 的值是任意的,但 Bravo 的值是其关联的 Alpha 的总和。出于性能(和成本)原因,Bravo 的值缓存在 DynamoDB table 中,并在更新 Alpha 时修改。

Alphas 使用简单的 AppSync DynamoDB PutItem 解析器进行更新,目的是通过观察 table 的流的 Lambda 函数更新其 Bravo 的值。这在大多数情况下效果很好;我可以给Alpha放随机值,我可以得到他们Bravo的值。

当我尝试在同一个请求中请求 Bravo 的值时出现问题。 (Lambda 函数需要一些时间从流中更新它。)

mutation putAlpha {
  putAlpha(alpha: {
      value: 10
  }) {
    id
    value
    bravo {
      value
    }
  }
}

当然这个 returns bravo 的旧缓存 value,因为在 Bravo 解析时 Lambda 函数还没有 运行。

是否有任何方法可以等到 DynamoDB 流的 Lambda 函数触发后再解析 bravo 或者使 PutItem 操作同步?

我能想到的唯一选择是使 putAlpha 解析器成为 Lambda 函数而不是简单的解析器,并在其中执行 Bravo 更新逻辑。

这种Lambda不断更新一个缓存值是正常的,还是我做错了?

如果您知道 运行 updateAlpha 时 Bravo 的下一个值应该是什么(例如,您不需要读取其他 Alpha),您可以使用 BatchPutItem 来更新两个 table秒。

如果不是,我认为 AppSync 目前不完全支持此用例。

要使其正常工作,您需要等待 Bravo 记录更新后才能读取它。我认为目前最简单的方法是使用 Lambda 函数。

您可以尝试的其他一些事情(它们有点老套):

  1. 让 putAlpha 变异解析器在一个循环中旋转指定的时间量,直到流更新 Bravo 记录。
  2. 在 Alpha.bravo 上添加一个解析器,它在从 table 读取之前在请求映射模板中等待 X 数量。
  3. 在 Bravo.value 上添加解析器,查询所有 Alpha,对它们的值求和,然后 returns 求和值。这种做法违背了在 Bravo 上存储值的目的。

我认为您不能在解析器中使用睡眠,但可以使用循环:https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-programming-guide.html#loops

希望对您有所帮助!

我认为您的客户应该知道 Bravo 的值是在后台计算的。 如果这不是您可以做出的权衡,请考虑将 Bravo 的更新逻辑移至 putAlpha 突变。 (为避免竞争条件,您可以使用 UpdateExpression 的 ADD 操作。)

一种方法是通过您 API 在您的信息流中更新 Bravo 的价值,并在您的客户端中订阅 Bravo 的更新。尽管您需要提供 window、xhr 等

,但可以在 Lambda 中 运行 aws-appsync

其他几种方式:

  1. 您可以增加 Bravo 在客户端缓存中的值,而不是从 putAlpha 的响应中获取它。
  2. Bravo 更新后您可以检索它的值。 (它可能会在几秒钟后更新。也许你有办法验证这个 Alpha 是否应用于 Bravo,将上次 Alpha 的更新时间存储到 Bravo 可以工作。)