EventBridge with AppSync JavaScript Resolvers
When building event-driven microservice applications, it becomes fairly common to make use of Amazon EventBridge as the messaging infrastructure between services.
Using an event-driven approach allows for loose coupling and asynchronous communication with services. This makes use of a choreography approach to coordination allowing for real-time notifications, serverless workflows, data synchronization, integration with third-party services, and audit logging and compliance.
Previously we have seen how to build GraphQL APIs in AWS AppSync using JavaScript and SQS as an HTTP endpoint. In this blog post, we will explore the direct integration of EventBridge with AWS AppSync to further support event-driven applications.
Getting Started
For this integration, we will demonstrate how we can send an event to EventBridge directly from our AWS AppSync JavaScript resolver using the EventBridge data source. We will configure an EventBridge Rule to trigger a Lambda function that will echo out the event message.
- We first start by creating an EventBridge event bus that we can target.
const eventBus = new EventBus(this, 'myEventBus', {
eventBusName: 'myEventBus',
});
2. Next we create an EventBridge data source in AWS AppSync targeting the event bus we just created.
const dataSource = api.addEventBridgeDataSource('dataSource', eventBus);
3. Next we define our AWS AppSync function containing the JavaScript resolver code. The name of the function matches the name of the action in our GraphQL schema.
const sendToEventBridgeFunction = new AppsyncFunction(this, 'eventBridgeFunction', {
name: 'eventBridgeFunction',
api: api,
dataSource: eventBridgeDataSource,
code: Code.fromAsset(path.join(__dirname, '/graphql/Events.sendEvent.js')),
runtime: FunctionRuntime.JS_1_0_0,
});
4. Once we have that setup we can write our AppSync JavaScript resolver function code.
// Events.sendEvent.js
import { util } from '@aws-appsync/utils';
export function request(ctx) {
return {
operation: 'PutEvents',
events: [
{
source: 'appsync',
detail: ctx.prev.result,
detailType: 'ItemCreated',
},
],
};
}
export function response(ctx) {
if (ctx.error) {
util.error(ctx.error.message, ctx.error.type, ctx.result);
}
return ctx.prev.result;
}
5. Just like we have seen before, we define our AppSync pipeline and JavaScript resolver.
const passthrough = InlineCode.fromInline(`
export function request(...args) {
return {}
}
export function response(ctx) {
return ctx.prev.result
}
`);
const eventBridgeResolver = new Resolver(this, 'eventBridgeResolver', {
api: api,
typeName: 'Mutation',
fieldName: 'createItem',
runtime: FunctionRuntime.JS_1_0_0,
pipelineConfig: [createItemFunction, sendToEventBridgeFunction],
code: passthrough,
});
6. To set up the event source mapping, we define our Lambda function that will process the event from EventBridge.
const echoFunction = new NodejsFunction(this, 'echoFunction', {
runtime: Runtime.NODEJS_18_X,
handler: 'handler',
entry: 'src/lambda/echo/main.ts'
});
7. Finally we define the EventBridge rule to trigger this Lambda function we created previously.
const echoRule = new Rule(this, 'AppSyncEventBridgeRule', {
eventBus: eventBus,
eventPattern: {
source: ['appsync'],
},
});
rule.addTarget(new LambdaFunction(echoFunction));
Testing our Integration
To test our GraphQL API we can execute our API mutation request. We can confirm in the CloudWatch Logs that our echo Lambda function was indeed triggered with the event received from EventBridge.
INFO {
version: '0',
id: 'ff7ce8e4-cfdf-b288-120c-88b304919c03',
'detail-type': 'ItemCreated',
source: 'appsync',
account: 'XXXXXXXXXXXX'
time: '2023-04-08T00:00:00Z',
region: 'us-east-1',
resources: [],
detail: { message: 'Hello from AppSync' }
}
This simple example demonstrates another powerful feature of using AWS AppSync JavaScript resolvers with EventBridge. The usefulness of this integration means we can greatly accelerate the development of event-driven architectures using GraphQL APIs.
Advanced Integrations
Having the ability to use EventBridge directly from a resolver allows for many possible integrations:
- Real-time notifications and alerts: trigger an event to EventBridge when a certain condition is met, such as when a new order is placed or a critical system event occurs. This event can then be consumed by other services or systems, enabling you to send notifications, update dashboards, or trigger automated actions.
- Orchestrating serverless workflows: invoke AWS Step Functions or AWS Lambda functions from an EventBridge event. This enables you to orchestrate complex business workflows, handle asynchronous processing, and coordinate multiple microservices seamlessly.
- Data synchronization and replication: emit events for specific data changes in your AppSync API that can then be captured and processed by other services or databases. This allows you to replicate data, update search indexes, or propagate changes to external systems.
EventBridge integrations using AppSync pipeline resolvers offer a wide range of use cases. These powerful capabilities enable you to build scalable, event-driven architectures and enhance the functionality and extensibility of your AppSync applications.
Eric Bach is a Senior Software Developer @Alberta Motor Association who enjoys learning, reading, and writing about leadership principles, event-driven microservices, and all things AWS.