GraphQL APIs with AWS AppSync: Part two

Introduction

This is the second of a series of posts describing my experimentation with AWS AppSync, Lambda, and DynamoDB. A public GitHub repository exists with this experiment so others can learn from my efforts. For this post, I will be describing the code that resides on the v1 tag, so feel free to checkout to this point in time: git checkout v1

Links to the other posts in this series are listed below:

The initial implementation

The implementation of the first version of the technical analysis investment engine will include the following:

  • GraphQL schema
  • AWS AppSync API
  • AWS Lambda resolver (implemented in Python 3.7)
  • Various AWS resources to map the AppSync GraphQL API to the Lambda resolver
  • Unit and integration tests for the Python handler and supporting code (the testing will be thoroughly described in the third post of this series)

Alpha Vantage integration

I will be using the Alpha Vantage APIs for investment data and analytics. A free API key can be obtained from Alpha Vantage by filling out this form. Copy the generated API key and paste it into a text file named .alphavantage in the root directory of this project. I have added an entry to the .gitignore file to exclude this hidden file from being version controlled.

Create a AWS named profile

I will be using AWS IAM to create an IAM user resource that has the AdministratorAccess Permission Policy. This will be the user that I use to provision all of the AWS resources for this experiment. AWS IAM best practices advises that you do not use your AWS account root user credentials to access AWS.

Instead, create an individual IAM user with administrative permissions for the work you will be performing on AWS. The AWS CLI allows you to maintain a named profile for each IAM user. The named profiles usage assumes you have AWS CLI installed and configured. Go here to install and configure the AWS CLI. Once you have configured and signed in to AWS, perform the following tasks:

  1. From the AWS Management Console, create an InvestGuruAdmin IAM user with the AdministratorAccess Permission Policy. Copy the Access Key ID and Secret Access Key for the next step.
  2. Create the InvestGuruAdmin named profile in your AWS credentials file (~/.aws/credentials) with the associated Access Key ID and Secret Access Key.

Creating the AWS resources

I used the Serverless Framework to scaffold out the initial AWS Lambda project. The Serverless Framework can do a lot more than just help facilitate the configuration and deployment of Lambda functions. One can include CloudFormation configuration that the Serverless Framework will use to create the associated AWS resources.

The Serverless Framework’s configuration file

The centerpiece of a Serverless Framework-managed application is the serverless.yml file. Its declarations specify everything about the project: cloud provider, plugins, runtime and deployment configuration to name just a few. A full listing of the options available through the aws provider within the serverless.yml file can be found here. The user guide for the aws provider can be found here.

Using CloudFormation YAML

AWS CloudFormation supports both JSON and YAML formats. I chose YAML as it works well with the Serverless Framework’s own serverless.yml YAML-based configuration file.

CloudFormation intrinsic functions

You will see a fair amount of intrinsic functions usage (e.g. Fn::GetAtt:!GetAtt) in my CloudFormation YAML. A full description of these functions can be found here. A little odd to work with at first, but once you get the hang of them, they aren’t too bad. I use the short form syntax in my serverless.yml file.

Serverless variables

I also use some Serverless Framework variables in the serverless.yml file. A full description of those can be found here. Again, super helpful for making the configuration modular. I especially like having the GraphQL schema in its own file (schema.graphql) and being able to edit it with syntax highlighting.

serverless.yml

The first forty-four lines of the serverless.yml file contain standard Serverless Framework YAML configuration, which is annotated below. Everything from line 48 on is AWS-specific CloudFormation YAML.

The GraphQL schema

I won’t belabor GraphQL here and why the schema is important. If you’re checking out this blog posting, you probably know what GraphQL is. If not, go here!

Our fledgling schema starts with a couple of custom types and a single query:

AWS Lambda handler

Our SimpleMovingAverageAnalytic AppSync resolver is an AWS Lambda function, implemented as a simple Python function:

Not much to look at, as most of the heavy lifting is delegated to the simple_moving_average function. We make two calls to this simple_moving_average function, retrieving the 50-day and 300-day simple moving averages for a stock. Finally a result dictionary is built and returned to the event source (in this case, AWS AppSync). A couple of things to note in this result dictionary:

  1. The structure of the dictionary matches the hierarchical/graph structure from the GraphQL Schema. The SimpleMovingAverageAnalytic type contains a single Company type and two lists, keyed by averages50 and averages300. Each element in the lists is of type MovingAverageObservation.
  2. Do not try to use standard Python snake_case with these keys in the result. The keys should remain in camelCase to match what GraphQL is going to map to. AppSync will puke if you don’t exactly match the keys specified in the GraphQL Schema.

simple_moving_average Python function

This function is pretty self-explanatory. Using the excellent Requests Python package, I will make a HTTP invocation on the Alpha Vantage SMA API for a company stock. Once we have the results, I transform the results into a format more suitable for our application.

Deploying the experiment to AWS

The package.json file contains deployment and undeployment scripts. To deploy the experiment, use yarn deploy-dev. That will deploy the experiment to the dev stage. You should see serverless deploy the experiment into AWS. At the end of the process, some key AWS configuration will be displayed. The AppSync URL and the API key for authenticating GraphQL requests will be displayed. Take note of these values, as you will need them for testing the deployment.

When completed with the experiment, use yarn undeploy-dev to remove the experiment from the dev stage and from AWS.

Testing the experiment deployed to AWS

All of this effort would be wasted if we couldn’t execute our GraphQL query and see real results come back. Alas, we can use GraphQL Playground to do just that. Below is the GraphQL query and HTTP headers that you can use to exercise the GraphQL API currently deployed into AWS. The API key from the deployment step is used in the HTTP headers as the x-api-key custom AWS header.

HTTP headers

Use the AppSync URL from the deployment step as the endpoint. The screenshot below demonstrates our simpleMovingAverageAnalytic GraphQL query.

Next steps

I’ll stop here so you have a chance to ingest this first iteration of our AppSync-hosted GraphQL API. The next post will cover using pytest to drive our test-driven development cadence.