AppSync GraphQL mutation server logic in resolvers
Asked Answered
M

2

9

I am having issues finding good sources for / figuring out how to correctly add server-side validation to my AppSync GraphQL mutations.

In essence I used AWS dashboard to define my AppSync schema, hence had DynamoDB tables created for me, plus some basic resolvers set up for the data.

No I need to achieve following:

  1. I have a player who has inventory and gold
  2. Player calls purchaseItem mutation with item_id
  3. Once this mutation is called I need to perform some checks in resolver i.e. check if item_id exists int 'Items' table of associated DynamoDB, check if player has enough gold, again in 'Players' table of associated DynamoDB, if so, write to Players DynamoDB table by adding item to their inventory and new subtracted gold amount.

I believe most efficient way to achieve this that will result in less cost and latency is to use "Apache Velocity" templating language for AppSync?

It would be great to see example of this showing how to Query / Write to DynamoDB, handle errors and resolve the mutation correctly.

Mcgill answered 17/10, 2018 at 7:39 Comment(2)
Thank you for the question. At this current time, AppSync resolver execute against a single data source. You can nest your queries to pass context between multiple resolvers as outlined in this article: hackernoon.com/… We are evaluating ways to do this without changing the schema structure and I will +1 your request. Please keep tuned to the latest AppSync announcements in the future.Guy
@LisaMShon thank you for relaying this to AppSync team. Meanwhile, is sollution like this viable? #52903982Mcgill
E
0

For writing to DynamoDB with VTL use the following tutorial

you can start with the PutItem template. My request template looks like this:

{
"version" : "2017-02-28",
"operation" : "PutItem",
"key" : {
    "noteId" : { "S" : "${context.arguments.noteId}" },
    "userId" : { "S" : "${context.identity.sub}" }
},
"attributeValues" : {
    "title" : { "S" : "${context.arguments.title}" },
    "content": { "S" : "${context.arguments.content}" }
}
}

For query:

{ "version" : "2017-02-28",
"operation" : "Query",
"query" : {
    ## Provide a query expression. **
    "expression": "userId = :userId",
    "expressionValues" : {
        ":userId" : {
            "S" : "${context.identity.sub}"
        }
    }
},
## Add 'limit' and 'nextToken' arguments to this field in your schema to implement pagination. **
"limit": #if(${context.arguments.limit}) ${context.arguments.limit} #else 20 #end,
"nextToken": #if(${context.arguments.nextToken}) "${context.arguments.nextToken}" #else null #end
 }

This is based on the Paginated Query template.

Ernesternesta answered 20/10, 2018 at 5:22 Comment(3)
I'm at this point now, my question translated to your example would go like this. For your PutItem example, how would you extend it to check that there is no other note with same title in the database before putting it in? I assume this requires additional query in that resolver plus some comparison logic and this is where I am stuck at the moment.Mcgill
@Mcgill see #19807188Ernesternesta
Thank you for the link that was useful, it works for this specific use case, but returning to my original question that implies more custom logic of purchasing item and updating users inventory and gold, this won't solve it (I just wanted to use example based on your question in previous comment to see how custom logic is handled in resolvers)Mcgill
M
0

What you want to look at is at Pipeline Resolvers: https://docs.aws.amazon.com/appsync/latest/devguide/pipeline-resolvers.html

Yes, this requires the VTL (Velocity Template)

That allows you to perform read, writes, validation, and anything you'd like using VTL. What you basically do is chain the inputs and outputs into the next template and make the required process.

Here's a Medium post showing you how to do it:

https://medium.com/@dabit3/intro-to-aws-appsync-pipeline-functions-3df87ceddac1

In other words, what you can do is: Have one template that queries the database, pipeline the result to another template that validates the result and inserts it if succeeds or fails it.

Moya answered 16/8, 2019 at 17:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.