9
votes

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.

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. - Lisa M Shon
@LisaMShon thank you for relaying this to AppSync team. Meanwhile, is sollution like this viable? stackoverflow.com/questions/52903482/… - Ilja

2 Answers

0
votes

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.

0
votes

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.