我有类似于以下的GraphQL架构 . 单个Bravo中有多个Alpha,它们各自具有相互引用 . (一个Bravo可以获得它的Alphas,一个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
}
如您所知,两种类型都有 Value . Alpha的值是任意的,但Bravo的值是其相关Alpha的总和 . 出于性能(和成本)原因,Bravo的值缓存在DynamoDB表中,并在更新Alpha时进行修改 .
使用简单的AppSync DynamoDB PutItem
解析器更新Alpha,其意图是通过观察表的流的Lambda函数更新其Bravo的值 . 这在大多数情况下效果很好;我可以给Alphas随机值,我可以得到他们的Bravo值 .
当我尝试在同一请求中请求Bravo的值时,会发生此问题 . (Lambda函数需要一些时间才能从流中更新它 . )
mutation putAlpha {
putAlpha(alpha: {
value: 10
}) {
id
value
bravo {
value
}
}
}
当然,这将返回 bravo
的旧缓存 value
,因为在解析Bravo时尚未运行Lambda函数 .
有没有办法等到DynamoDB流的Lambda函数在解析 bravo
之前触发,或者可能使 PutItem
操作同步?
我能想到的唯一选择是让 putAlpha
解析器成为Lambda函数而不是简单的解析器,并在那里进行Bravo更新逻辑 .
这种Lambda是否会不断更新缓存值,或者我做错了什么?
2 回答
我认为您的客户应该知道Bravo的 Value 是在后台计算的 . 如果这不是您可以做出的权衡,请考虑将Bravo的更新逻辑移至putAlpha变异 . (为避免竞争条件,您可以使用UpdateExpression的ADD操作 . )
一种方法是通过您的流中的API更新Bravo的 Value ,并在您的客户端订阅Bravo的更新 . 虽然你需要提供窗口,xhr等,但可以在Lambda中运行aws-appsync .
其他几种方式:
您可以增加Bravo 's value in client'的缓存,而不是从putAlpha的响应中获取它 .
您可以检索更新的Bravo 's value once it' . (它可能会在几秒钟后更新 . 也许你有办法验证这个Alpha是否应用于Bravo,将最后Alpha的更新时间存储到Bravo可能有效 . )
如果您知道运行updateAlpha时Bravo的下一个值应该是什么(例如,您不需要读取其他Alpha),则可以使用BatchPutItem更新两个表 .
如果没有,我不相信AppSync现在完全支持这个用例 .
为了使其工作,您需要等待Bravo记录在阅读之前得到更新 . 我认为目前最简单的方法是使用Lambda函数 .
你可以尝试的其他一些事情(他们有点hacky):
使putAlpha突变解析器在循环中旋转指定的时间,直到流更新Bravo记录 .
在Alpha.bravo上添加一个解析器,在从表中读取之前等待请求映射模板中的X金额 .
在Bravo.value上添加一个解析器,它查询所有Alpha,汇总它们的值,然后返回求和值 . 这种方式违背了在Bravo上存储 Value 的目的 .
我不是't think you can use a sleep in the resolver',但你可以使用循环:https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-programming-guide.html#loops
希望这可以帮助!