使用 Graphql 和 Amplify/AppSync 基于先前值的变异

Mutation based on previous value with Graphql and Amplify/AppSync

我想指出我是 Graphql 的新手,我可能遗漏了一些明显的东西。我想做一些类似于商店订单系统的事情。当客户购买东西时,会完成两件事:(1) 钱从他的钱包中减少,以及 (2) 将一个订单添加到他的订单历史记录中。截至目前,我将钱包和订单历史建模为 GraphQL 模式中的两种类型。

第 1 点。 理想情况下,我想要进行交易。如果钱包更新或订单创建失败,则整体应该失败。据我了解,要将其存档,如 this answer 中所指出的那样,只需一个突变即可完成两个更新。 那么,我是否理解正确,像这样的东西就像事务一样工作(在失败的情况下回滚)?

mutation {
   update_wallet(...) {...}
   add_to_history(...) {...}
}

第 2 点。 其次,我想存储每位顾客购买的平均数量。为此,我想使用增量平均函数 (this one),所以我想存储当前平均值并用公式更新它。但是,我不明白如何“安全地”做到这一点(没有可能的竞争条件)。据我了解,GraphQL 中有一个原子增量选项,仅此而已。所以我想我可以存储 sum_of_all_the_items 和 number_of_purchases 以便计算每个请求的除法。这可能没问题,即使它看起来不是最干净的解决方案。特别是因为这些数字会无限增长并最终(即使是非常不幸的情况)溢出。

谢谢

这是您 AppSync 背后的数据库的问题。它可能是 DynamoDb 或 RDS。通常,您只需要一个执行客户购买的突变,包括

  1. 从钱包里扣钱
  2. 从库存中扣除一些物品
  3. Add/Update一条订单记录(orderId, userId, numberOfItems, status)
  4. 添加购买记录(orderId,purchaseId,更多购买信息)

所有这些都在单个事务中执行。如果您的数据库是 RDS,那么您可以通过对订单 table 的 SQL 查询轻松计算出平均项目数。人数实时汇总,不存在竞态

另一方面,如果是DynamoDb,this answer. Race conditions in DynamoDb can be a different problem, and one solution I know is conditional update中有很多选项。

一个突变应该足以满足您的情况。突变 purchaseWithoutOrder 用于没有订单的购买。

type Mutation {
  purchase(orderId: ID!): PurchaseResult
  purchaseWithoutOrder(input: PurchaseWithoutOrderInput!): PurchaseResult
}

type PurchaseWithoutOrderInput {
  items: [Item!]!
}