Skip to content

Commit

Permalink
Add json field (#31)
Browse files Browse the repository at this point in the history
* return only the first element of Records for S3 events
* add json field, when publish message it will be stringified, then parsed back to json when consume the message
* add limitation of maximum 256KB message so we can catch the error if json filed is too large
  • Loading branch information
shawn-cx-li authored Sep 23, 2020
1 parent 1eaa6f0 commit 71d9b61
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 5 deletions.
2 changes: 2 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ declare module "@luxuryescapes/lib-events" {
const PROPERTY_UPDATE: string;
const PROPERTY_DELETE: string;

const ROOM_AVAILABILITY_UPDATE: string;

const HOTEL_RESERVATION_SITEMINDER_ERROR: string;
const HOTEL_RESERVATION_TRAVELCLICK_ERROR: string;

Expand Down
57 changes: 53 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const sns = new AWS.SNS({
region: process.env.AWS_SNS_REGION
});

// Amazon SNS currently allows a maximum size of 256 KB for published messages.
const MAX_EVENT_MESSAGE_SIZE = 256 * 1024;

const typeList = [
"ORDER_PENDING",
"ORDER_COMPLETED",
Expand Down Expand Up @@ -98,7 +101,23 @@ class InvalidEventMessageError extends Error {
}
}

function dispatch({ type, uri, id, checksum, source, message }) {
class InvalidEventJsonError extends Error {
constructor(message, status) {
super(message);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}

class InvalidEventSizeError extends Error {
constructor(message, status) {
super(message);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}

function dispatch({ type, uri, id, checksum, source, message, json }) {
if (!types[type]) {
throw new InvalidEventTypeError(`invalid event type '${type}'`);
}
Expand All @@ -115,6 +134,13 @@ function dispatch({ type, uri, id, checksum, source, message }) {
throw new InvalidEventMessageError("event message is required");
}

let jsonStr;
try {
jsonStr = JSON.stringify(json);
} catch (e) {
throw new InvalidEventJsonError("event json is invalid");
}

const messageAttributes = {
type: {
DataType: "String",
Expand All @@ -127,6 +153,10 @@ function dispatch({ type, uri, id, checksum, source, message }) {
source: {
DataType: "String",
StringValue: source
},
json: {
DataType: "String",
StringValue: jsonStr
}
};

Expand All @@ -150,6 +180,13 @@ function dispatch({ type, uri, id, checksum, source, message }) {
Message: message
};

if (
Buffer.byteLength(JSON.stringify(eventParams), "utf8") >
MAX_EVENT_MESSAGE_SIZE
) {
throw new InvalidEventSizeError("json message exceeded limit of 256KB");
}

if (process.env.IGNORE_EVENTS == "true") {
return Promise.resolve();
}
Expand Down Expand Up @@ -191,7 +228,9 @@ function deleteMessage(message) {
function getAttributes(body) {
const bodyJson = JSON.parse(body);
// handle s3 upload event
if (bodyJson.Records) return bodyJson.Records;
// currently we can only one record per s3 event
// https://stackoverflow.com/questions/40765699/how-many-records-can-be-in-s3-put-event-lambda-trigger/40767563#40767563
if (bodyJson.Records) return bodyJson.Records[0];
else if (bodyJson.MessageAttributes) {
// handle sns message
return mapAttributes(bodyJson);
Expand All @@ -204,12 +243,22 @@ function getAttributes(body) {
function mapAttributes(data) {
const attributeReducer = (accumulator, currentValue) => {
if (data.MessageAttributes[currentValue]) {
accumulator[currentValue] = data.MessageAttributes[currentValue].Value;
if (currentValue === "json") {
try {
accumulator[currentValue] = JSON.parse(
data.MessageAttributes[currentValue].Value
);
} catch (e) {
throw new InvalidEventJsonError(`unable to parse json`);
}
} else {
accumulator[currentValue] = data.MessageAttributes[currentValue].Value;
}
}
return accumulator;
};

const attributeList = ["type", "uri", "id", "checksum"];
const attributeList = ["type", "uri", "id", "checksum", "json"];

return attributeList.reduce(attributeReducer, {});
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@luxuryescapes/lib-events",
"version": "1.0.30",
"version": "1.0.31",
"main": "index.js",
"scripts": {
"test": "./node_modules/.bin/jest && yarn run lint",
Expand Down

0 comments on commit 71d9b61

Please sign in to comment.