NestJS
AWS SQS Server on NestJS
Notes on structuring an SQS-driven server with NestJS.
This processes controller entries with @EventPattern({}) or @EventPattern('') for null entries.
import { Logger } from '@nestjs/common';
import { CustomTransportStrategy, Server } from '@nestjs/microservices';
import { Context, SQSEvent, SQSRecord } from 'aws-lambda';
export class AWSSQSServer extends Server implements CustomTransportStrategy {
event: SQSEvent;
context: Context;
constructor(event: SQSEvent, context: any) {
super();
this.event = event;
this.context = context;
}
/**
* This method is triggered when you run "app.listen()".
*/
async listen(callback: () => void) {
const records = this.getRecords();
for await (const record of records) {
const key = this.getMessageAttribute(record);
const msg = this.getMessage(record);
Logger.debug(key, 'SQSKey');
Logger.debug(msg, 'SQSMessage');
Logger.debug(record, 'SQSRecord');
Logger.log([...this.messageHandlers.keys()]);
const handler = this.messageHandlers.get(key);
if (handler) {
await handler(msg, this.context);
} else {
Logger.error(`${key} is not a valid handler.`);
}
}
callback();
}
/**
* This method is triggered on application shutdown.
*/
close() {
return;
}
/**
* This method converts all messageAttributes to a string with format `key:value`.
* Example:
* MessageAttributeMap: `[{ key2: value1, key2: value2 }]`
* Output: [{ 0: key1:value1, 1: key2:value2}]
* @private
* @param {SQSRecord} record
* @return {*} {string}
* @memberof AWSSQSServer
*/
private getMessageAttribute(record: SQSRecord): string {
const messageAttributeMap = record.messageAttributes;
const returnArray: string[] = [];
Object.keys(messageAttributeMap).forEach((key) => {
returnArray.push(`${key}:${messageAttributeMap[key].stringValue}`);
});
const stringifiedKey = JSON.stringify(Object.assign({}, returnArray));
return stringifiedKey === '{}' ? '' : stringifiedKey;
}
/**
* This returns the Message part of SQS
*/
private getMessage(record: SQSRecord): any {
return record.body;
}
private getRecords(): SQSRecord[] {
return this.event.Records;
}
}