Reputation: 729
I encounter a weird behavior when I run a Lambda with Node v12 runtime.
This lambda is triggered by a cloudwatch event rule.
It's purpose is to perform a certain operation, and then reschedule the rule to be invoked after a specific period (ex 5 minutes).
exports.handler= async function (event, context, callback) {
console.info('Hello world');
let nextValue = moment().add(5, 'minutes');
let cronValue = `cron(${nextValue .minutes()} ${nextValue .hours()}
${nextValue .date()} ${nextValue .month() + 1} ? ${nextValue .year()})`;
let putRuleParams = {
Name: RuleName,
Description: `Rechedule event`,
ScheduleExpression: cronValue,
};
console.info(`Updating rule ${RuleName}. Params: `, putRuleParams);
cloudwatchevents.putRule(putRuleParams, function(err, data) {
if (err) {
console.error('Error updating rule', err);
} else {
console.info('Successfully updated rule', data);
}
});
console.info('After execution');
}
The output is the following
2020-01-31T14:19:07.749Z 97c23991-7710-4d98-accd-943b470d0875 INFO Updating rule fiv-
loadpartitions_rule. Params: {
Name: 'dummy_rule',
State: 'DISABLED',
Description: 'Scheduled on 31-01-2020 14:24 +00:00 to load partitions for generic_amount_tb
table.',
ScheduleExpression: 'cron(24 14 31 1 ? 2020)'
}
2020-01-31T14:19:07.751Z 97c23991-7710-4d98-accd-943b470d0875 INFO After execution
END RequestId: 97c23991-7710-4d98-accd-943b470d0875
REPORT RequestId: 97c23991-7710-4d98-accd-943b470d0875 Duration: 15639.87 ms Billed Duration:
15700 ms Memory Size: 1536 MB Max Memory Used: 101 MB Init Duration: 398.67 ms
As you can see the update rule callback handler is not executed, as function execution ends before the event is completed. And there is no update on rule in AWS. How can I tell to Lambda to wait until the event is completed?
Upvotes: 3
Views: 4010
Reputation: 7770
You are not waiting for your function to get completed. Use promise version and add await. Try this
exports.handler = async function (event, context, callback) {
console.info("Hello world");
const nextValue = moment().add(5, "minutes");
const cronValue = `cron(${nextValue .minutes()} ${nextValue .hours()}
${nextValue .date()} ${nextValue .month() + 1} ? ${nextValue .year()})`;
const putRuleParams = {
"Name": RuleName,
"Description": "Rechedule event",
"ScheduleExpression": cronValue
};
console.info(`Updating rule ${RuleName}. Params: `, putRuleParams);
const response = await cloudwatchevents.putRule(putRuleParams).promise();
return response;
console.info("After execution");
};
you can use any of the aws sdk's method in a promise way by adding .promise()
at the end.
Upvotes: 1
Reputation: 8887
You really have two options here.
async
from your function. That should keep the Lambda running until the event loop runs out or the lambda times out.await
it. You can just add .promise()
to the end of the call, and the response to the call will be the data you'd put in your callback.https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
Upvotes: 4