问题描述
我想指出我是 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。通常,您只需要一个执行客户购买的变更,包括
- 从钱包里扣钱
- 从库存中扣除一些物品
- 添加/更新订单记录(orderId、userId、numberOfItems、status)
- 添加购买记录(orderId、purchaseId、更多购买信息)
所有这些都在单个事务中执行。如果您的数据库是 RDS,那么您可以通过对 Order 表的 SQL 查询轻松计算出平均项目数。数量是实时聚合的,没有竞争条件。
另一方面,如果是 DynamoDb,则 this answer 中有很多选项。 DynamoDb 中的竞争条件可能是一个不同的问题,我知道的一个解决方案是 conditional update。
对于您的情况,一个突变应该就足够了。突变 purchaseWithoutOrder
用于没有订单的购买。
type Mutation {
purchase(orderId: ID!): PurchaseResult
purchaseWithoutOrder(input: PurchaseWithoutOrderInput!): PurchaseResult
}
type PurchaseWithoutOrderInput {
items: [Item!]!
}