Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda execution quits before asynchronous event is finished

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?

like image 843
csm86 Avatar asked Aug 08 '26 05:08

csm86


2 Answers

You really have two options here.

  1. Remove the async from your function. That should keep the Lambda running until the event loop runs out or the lambda times out.
  2. Change your callback to be a promise and 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

like image 95
Jason Wadsworth Avatar answered Aug 10 '26 19:08

Jason Wadsworth


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.

like image 28
Ashish Modi Avatar answered Aug 10 '26 19:08

Ashish Modi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!