How do I notify AWS AppSync subscribers of external database updates that aren't performed through mutations?

Last updated: 2020-02-27

I need my app's clients to update in real time for external database changes. How do I use AWS AppSync to notify subscribers of these changes?

Short Description

Use local resolvers to instantly notify subscribers of external database changes without needing to trigger a data source call. This is useful when subscribers need real-time data, such as in an airline app that needs the latest pricing and flight times.

Follow these instructions to create an example GraphQL API that updates subscribers in real time when data is written to an Amazon DynamoDB table data source.

Resolution

Create a GraphQL API using the wizard

Use the AWS AppSync guided schema wizard to create a new GraphQL API. For more information, see Designing a GraphQL API.

1.    Open the AWS AppSync console.

2.    Choose Create API.

3.    On the Getting Started page, under Customize your API or import from Amazon DynamoDB, choose Create with wizard, and then choose Start.

4.    On the Create a model page, do the following:
Under Name the model, you can enter a name for your model. For this example setup, leave the model name (MyModelType) unchanged.
Under Configure model fields, you can define the data types for your app. For this example setup, leave the default field names (id and title) and types unchanged.
(Optional) Expand Configure model table (optional) to add an index.
Choose Create.

5.    On the Create resources page, enter a name for your API, and then choose Create. AWS AppSync creates your API as specified and opens the Queries page of your API.

Create a test subscription

1.    In the AWS AppSync console, on the Queries page of your API, open a duplicate browser tab or window.

2.    In the duplicate browser tab or window, in the query editor, enter the following:

subscription sub1 {
  onCreateMyModelType{
    id
    title
  }
}

This operation creates a subscription to createMyModelType mutations.

3.    Choose the play button (Execute Query), and then choose sub1. The duplicate browser tab or window is subscribed to the mutation.

4.    In the original browser tab or window, choose the play button (Execute Query), and then choose createMyModelType. This executes the mutation, and you can see the results in both the original and duplicate (subscription) browser tabs or windows.

5.    Close the duplicate browser tab or window after you see the subscription behavior demonstrated.

Create a None type data source

The None data source type passes the request mapping template directly to the response mapping template.

1.    In the original browser tab or window, in the left navigation pane of the AWS AppSync console, choose Data Sources.

2.    Choose Create Data Source.

3.    On the New Data Source page, under Create new Data Source, do the following:
For Data source name, enter a name. For example, real_time_data.
For Data source type, choose None.

4.    Choose Create.

For more information, see Attaching a Data Source.

Add a mutation to the schema

Update the schema with a mutation that passes database updates to the None type data source.

1.    In the left navigation pane of the AWS AppSync console, choose Schema.

2.    In the schema editor, under type Mutation {, overwrite this:

    createMyModelType(input: CreateMyModelTypeInput!): MyModelType

With this:

    addMyModelType(id : ID! , title : String!): MyModelType

3.    In the schema editor, under type Subscription {, overwrite this:

        @aws_subscribe(mutations: ["createMyModelType"])

With this:

        @aws_subscribe(mutations: ["addMyModelType"])

Note: You can also create a new mutation type and the corresponding subscription instead of overwriting these.

4.    Choose Save Schema.

For more information, see Designing Your Schema.

Attach a resolver to the subscription

1.    In the AWS AppSync console, on the Schema page of your API, under Resolvers, scroll down to Mutation. Or, for Filter types, enter Mutation.

2.    Next to addMyModelType(...): MyModelType, under Resolver, choose Attach.

3.    On the Create new Resolver page, for Data source name, choose the name of the None type data source that you created earlier. (For example, real_time_data.)

4.    Under Configure the request mapping template, overwrite this:

    "payload": {
        "hello": "local",
    }

With this:

    "payload": $util.toJson($context.args)

4.    Choose Save Resolver.

For more information, see Configuring Resolvers.

Create a new test subscription

1.    In the AWS AppSync console, in the left navigation pane, choose Queries.

2.    On the Queries page of your API, open a duplicate browser tab or window.

3.    In the duplicate browser tab or window, in the query editor, overwrite this:

mutation createMyModelType($createmymodeltypeinput: CreateMyModelTypeInput!) {
  createMyModelType(input: $createmymodeltypeinput) {
    id
    title
  }
}

With this:

subscription sub1 {
  onCreateMyModelType{
    id
    title
  }
}

4.    Choose the play button (Execute Query), and then choose sub2. The duplicate browser tab or window is subscribed to the mutation.

Create a new test mutation

1.    In the original browser tab or window, on the Queries page of your API, in the query editor, overwrite this:

mutation createMyModelType($createmymodeltypeinput: CreateMyModelTypeInput!) {
  createMyModelType(input: $createmymodeltypeinput) {
    id
    title
  }
}

With this:

mutation mutation1 {
  addMyModelType(id:"5",title:"new update"){
    id
    title
  }
}

This operation creates an addMyModelType mutation.

2.    Choose the play button (Execute Query), and then choose mutation1.

3.    In the duplicate (subscription) browser tab or window, see that the subscriber receives the update in real time.

(Optional) Refer to examples use cases

As you build your client app and apply these concepts, consider the example use case of an airline app that provides pricing and flight times. In this case, to notify subscribed clients when flight details change in a DynamoDB table, do the following:

1.    Create an AWS Lambda function that uses a DynamoDB stream as the trigger. The Lambda function is triggered whenever there's an update to the DynamoDB table. For more information, see Using AWS Lambda with Amazon DynamoDB.

2.    In the Lambda function code, include logic to filter the appropriate updates and perform a mutation call to AWS AppSync. This causes AWS AppSync to notify subscribers through the subscription. For more information, see Tutorial: AWS Lambda Resolvers.

3.    In AWS AppSync, add a new mutation field (for example, named publishPrice) with a local resolver.

4.    Subscribe to that mutation in a subscription field (for example, named onPriceUpdate). The schema might look like the following:

type flightDetails {
  id: ID!
  src: String!
  destn: String!
  price : Int
}

type Mutation {
   # A local resolver targeting a None data source that publishes the message to subscribed clients.
  publishPrice(price: Int): flightDetails
}

type Subscription {
  # Notified whenever *publishPrice* is called.
  onPriceUpdate: Message
    @aws_subscribe(mutations: ["publishPrice"])
}

type Query { ... }

For more information, see Designing Your Schema.

5.    Create another AWS Lambda function that uses a DynamoDB stream as the trigger. In this function, call the publishPrice mutation. Because the publishPrice mutation has a local resolver, the data isn't written to DynamoDB again. In this way, you can use AWS AppSync as a PubSub broker.

For more information and another example use case, see Tutorial: Local Resolvers.


Did this article help you?

Anything we could improve?


Need more help?