I have an issue with a lambda function I am developing for a personal project - budget/payment system. The intent of the lambda is to pull messages from an SQS queue, each record/message is processed by the lambda where some helper functions (calcDateUsingDayInterval() and calcMonths() - these use a lambda layer for dependency and utilise the date-fns JS library) are called to plot out dates, based on input frequency. The idea is that these output dates will be added to another SQS queue, and then processed by a rest API (lambda) which will POST records to a dynamodb table. BUT for now, I am just trying to log each output to show that the function is actually working. When this lambda is invoked by the event source mapping attached to the queue, it looks like the function exits early and doesnt wait for the result.
I have been developing the function just using nodejs locally, and then lifting the config into lambda. When I run this in nodejs locally, I get the expected output (logged events based on "frequency".) Here is my lambda code:
const {
addDays,
addMonths,
differenceInCalendarMonths,
eachDayOfInterval,
formatISO,
} = require("date-fns");
const AWS = require("aws-sdk");
exports.handler = async function (event, context) {
event.Records.forEach((record) => {
const { body } = record;
console.log(body); // I can see this in cloudwatch logs
// Day Function
function calcDateUsingDayInterval(startDate, endDate, step) {
const dayRange = eachDayOfInterval(
{ start: startDate, end: endDate },
{ step: step }
);
dayRange.forEach((day) => {
console.log({
id: AWS.util.uuid.v4(),
parentId: body.parentId,
date: formatISO(day, { representation: "date" }),
name: body.name,
description: body.description,
vendor: body.vendor,
frequency: body.frequency,
value: body.value,
type: body.type,
status: body.status,
forecastId: body.forecastId,
event_time: new Date().toISOString(),
});
});
}
// Month Function
function calcMonths(endDate, startDate, step) {
// Calculate the number of months in the date range - used as the condition in the loop
const months = differenceInCalendarMonths(endDate, startDate);
// Iterate through the number of months by the step range
for (let i = step; i <= months; i += step) {
const date = addMonths(startDate, i);
console.log({
id: AWS.util.uuid.v4(),
parentId: body.parentId,
date: formatISO(date, { representation: "date" }),
name: body.name,
description: body.description,
vendor: body.vendor,
frequency: body.frequency,
value: body.value,
type: body.type,
status: body.status,
forecastId: body.forecastId,
event_time: new Date().toISOString(),
});
}
}
try { // This does nothing in the lambda function - but works in node locally
switch (body.frequency) {
case 0:
calcDateUsingDayInterval(body.startDate, body.startDate, 1)
break;
case 1:
calcDateUsingDayInterval(body.startDate, body.endDate, 1)
break;
case 2:
calcDateUsingDayInterval(body.startDate, body.endDate, 7)
break;
case 3:
calcDateUsingDayInterval(body.startDate, body.endDate, 14)
break;
case 4:
calcMonths(body.endDate, body.startDate, 1)
break;
case 5:
calcMonths(body.endDate, body.startDate, 3)
break;
case 6:
calcDateUsingDayInterval(body.startDate, body.endDate, 365)
break;
default:
throw new Error(`Unsupported frequency integer: "${body.frequency}"`)
}
}
catch {
// To do
}
finally {
// To do
}
});
return {};
};
Based on my research I expect this is something to do with my lambda handler function being Async, because of this it looks like I need to return a promise. I dont properly understand JS promises - tried a few things and couldnt get it to work. I am a self taught hack.
Questions
Does this lambda handler even need to be Async if its processing messages from an SQS queue? - Number of functions should scale horizontally based on input.
Can this be optimised so my helper functions werent inside
event.Records.forEach? I guess I could use a lambda layer for this also? Any help with code formatting to optimise/minimise invocation run time is also appreciated. I wasnt sure how to get access to thebodyobject for logging if the functions were outside the loop.
Thanks