Unlock the Power of Event-Driven Architecture with AppSync's EventBridge Data Source

Unlock the Power of Event-Driven Architecture with AppSync's EventBridge Data Source

Learn About AppSync's EventBridge Integration with a Practical Example

AppSync is a fully managed service provided by Amazon Web Services (AWS) that simplifies the process of building scalable APIs for web and mobile applications. It allows developers to easily create GraphQL APIs that can be connected to various data sources, including AWS services like DynamoDB and Lambda functions.

The AppSync team recently added support for EventBridge as a data source. In this article, we will see how it works and how you can use it with a practical example.

How it works

The EventBridge data source is a new addition that streamlines integration between AppSync and EventBridge. Previously, events could be sent to EventBridge via an HTTP data source, but that required more complex resolvers, better knowledge of the events API, and more IaC to sign HTTP requests with sigv4. Now, with the new native EventBridge data source, AWS AppSync automatically handles all of the complex tasks, leaving you to simply write a simple resolver request operation.

Here is what a request looks like:

{
  operation: 'PutEvents',
  events: [
    {
      source: 'AppSync', // it can be anything
      detailType: 'myEvent',
      detail: {
        foo: 'bar',
      },
    },
  ],
}

You can put up to 10 events in the same request. Just pass them as an array in the events property.

Note that the EventBridge Data "Source" is a bit special in that it's write-only. The only operation you can do is PutEvents.

The response to the request returns information relative to the events that were put on the bus.

{
  "Entries": [
    {
      "EventId": "3298e5f9-66a6-ece5-f0c7-9ff791bcfd1e"
    }
  ],
  "FailedEntryCount": 0
}

📚 For more information, see the documentation

A Practical Example

Great, but how can it be used? Let's take an example.

Imagine that you are building a blog application. Each time that someone publishes a new blog post, you want to notify the followers of the author via email to let them know about it (Similar to Hashnode's Newsletter feature).

One way to do this is by using an Event-Driven approach. EventBridge is often associated with Event-Driven applications. This involves publishing an event, such as postCreated to an event bus after the post is created. Next, you can set up an EventBridge rule that triggers a Lambda function or a Step Function workflow. This workflow can then retrieve all subscribers for the author, construct an email, and send it out.

Let's have a look at how we can implement this using AppSync pipeline resolvers and the new EventBridge data source integration.

To achieve this, we are going to use two functions in our pipeline. Let's call them createPost and putEvent.

The first step is createPost, which utilizes a DynamoDB data source. With the use of a PutItem operation, it inserts the post into a table. Following it, putEvent takes advantage of the new EventBridge integration to place an event on the event bus.

CreatePost Pipeline resolver overview

The handlers are as follows:

// createPost.js
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const item = {
    ...ctx.args.post,
    createdAt: util.time.nowISO8601(),
    updatedAt: util.time.nowISO8601(),
  };
  return {
    operation: 'PutItem',
    key: {
      id: util.dynamodb.toDynamoDB(util.autoId()),
    },
    attributeValues: util.dynamodb.toMapValues(item),
    condition: {
      expression: 'attribute_not_exists(#id)',
      expressionNames: {
        '#id': 'id',
      },
    },
  };
}

export function response(ctx) {
  ctx.stash.event = {
    detailType: 'postCreated',
    detail: ctx.result,
  };

  return ctx.result;
}

In the response handler, we first build the event that is going to be put into EventBridge. It contains the detailType (postCreated) and the detail information which is the post item that was just inserted into DynamoDB. Before we return, we stash it. The returned value of the resolver is the post itself.

Pre-constructing the event in createPost allows us to keep the putEvent function more generic and reusable. i.e. It only has to call PutEvents with the data coming from the previous step (stashed) and does not have to deal with specificities.

// putEvent.js
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  if (!ctx.stash.event) {
    util.error('InternalError', 'Event missing in stash');
  }

  return {
    operation: 'PutEvents',
    events: [
      {
        source: 'blog-appsync-api',
        ...ctx.stash.event,
      },
    ],
  };
}

export function response(ctx) {
  if (ctx.error) {
    util.error('Failed putting event in EventBride', 'Error');
  }

  return ctx.prev.result;
}

The response handler returns the result from the previous function, that is the post item that was inserted. This is also the value that is returned by the pipeline resolver to the client. The EventBridge step is completely transparent.

Let's test it.

GraphBolt is a tool that helps developers build and test AppSync APIs. Thanks to the embedded GraphQL client, you can easily execute queries and mutations. I'm going to use it to call the createPost Mutation.

The Mutation returned the inserted post, proving that the resolver works as expected.

The Mutation returned the inserted post, meaning that the resolver works as expected. But how about the event?

GraphBolt also comes with a debugger that lets you see what happened under the hood of a resolver. Let's check it out.

As you can see, the putEvent function was invoked, and it put an event into EventBridge with the content of the post, as expected (right side of the image).

To double-check it, I also created an EventBridge rule that triggers a Lambda function and prints the event into CloudWatch.

💡 You can find a fully functional example of this on GitHub, using the Serverless Framework.

Conclusion

In this article, we learned about the new EventBridge data source integration in AWS AppSync. We saw how this integration streamlines the process of building event-driven applications by allowing developers to easily publish events from AppSync resolvers to EventBridge. We also saw a practical example of how to implement this. Overall, this new feature enhances the capabilities of AWS AppSync and provides developers with a powerful tool for building modern serverless APIs.