I have GraphQL schema similar to the following. There are multiple Alphas in a single Bravo, and they each have a reference to each other. (A Bravo can get its Alphas, and an Alpha can get its 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
}
As you can tell, both types have a value. The value of Alpha is arbitrary, but the value of Bravo is the sum of its associated Alphas. For performance (and cost) reasons, the Bravo's value is cached in the DynamoDB table and modified whenever an Alpha is updated.
Alphas are updated with a simple AppSync DynamoDB PutItem
resolver, with the intention being that the value of its Bravo would be updated by a Lambda function watching the table's stream. This works well for the most part; I can put Alphas with random values, and I can get the value of their Bravo.
The problem occurs when I try to request the value of the Bravo in the same request. (The Lambda function takes some time to update it from the stream.)
mutation putAlpha {
putAlpha(alpha: {
value: 10
}) {
id
value
bravo {
value
}
}
}
Naturally this returns the old cached value
of bravo
, because the Lambda function hasn't been run by the time the Bravo is resolved.
Is there any way to wait until the DynamoDB stream's Lambda function has fired before resolving bravo
or perhaps make the PutItem
operation synchronous?
The only alternative I can think of is to make the putAlpha
resolver a Lambda function instead of a simple resolver and do the Bravo updating logic in there.
Is this kind of Lambda continuously updating a cache value normal, or am I doing something wrong?
I think that your client should be aware that Bravo's value is calculated in the background. If that's not a tradeoff that you can make, consider moving Bravo's update logic to putAlpha mutation. (To avoid race conditions you can use UpdateExpression's ADD action.)
One way would be to update Bravo's value through you API in your stream and subscribe to Bravo's updates in your client. It is possible to run aws-appsync in Lambda though you need to provide window, xhr etc.
Couple of other ways: