jmwright
jmwright

Reputation: 131

Sequelize Code Not Executing Inside AWS Lambda

I've got Sequelize-based code that runs fine in a Node.js project. I moved that code into an AWS Lambda handler and am testing it with the node-lambda module. Now the Sequelize code seems to be skipped. I'm not sure if the promise isn't being handled before the Lambda finishes, or if I'm missing something else. The following code skips the "during" console.log as shown in the output below.

var models  = require('./models');

exports.handler = function( event, context, callback ) {
    console.log("Before");

    var body = JSON.parse(event.body);

    // Find the device ID from the devices table
    models.Device.findOne({where: {device_uuid: body.device_uuid}, attributes: ['id']}).then(function(device) {
        console.log("During");

        // Make sure that we got a device back
        if (device === null) {
            console.log("Device not found - could not insert data");
            return;
        }
        else {
            console.log("Device found, inserting data - " + body.device_uuid);

            //Insert the data for this device
            models.Data.create({
               device_id: device.id,              
               data: body.data
            });
        }
    });

    console.log("After");

    callback(null, "{\"status\": \"success\"}");
}

Yields...

Before
After
Success:
"{\"status\": \"success\"}"

Any ideas on where I'm going wrong? I'm using Node v5.9.0.

Upvotes: 1

Views: 2091

Answers (2)

Steven Yong
Steven Yong

Reputation: 5446

Spent me almost a day to figure out what's wrong as I have the exact same issue.

Turn out I need to put await to those function which interact with database using sequelize, else Lambda will just exits.

module.exports.v2BlacklistEmails = async (event, context) => {    

  try {
    const message = JSON.parse(event.Records[0].Sns.Message)

    switch (message.notificationType) {
      case "Bounce":
        handleBounce(message);
        break;
    }
  } catch (err) {
    console.log("Error processing event: " + err.stack)
  }
}

function handleBounce(message) {
  const messageId = message.mail.messageId
  const addresses = message.bounce.bouncedRecipients.map(function (recipient) {
    return recipient.emailAddress
  })
  const bounceType = message.bounce.bounceType

  console.log("Message " + messageId + " bounced when sending to " + addresses.join(", ") + ". Bounce type: " + bounceType)
  for (var i = 0; i < addresses.length; i++) {
    if (addresses[i] !== process.env.BOUNCE_EMAIL_AU && addresses[i] !== process.env.BOUNCE_EMAIL_NZ) {
      utils.blacklistEmailsIntoDB(decryptedUser, decryptedPassword, addresses[i])
    } else {
      console.log("Mailbox " + addresses[i] + " maybe full, please check.")
    }
  }
}

So I have to put await at:

handleBounce(message);

and

utils.blacklistEmailsIntoDB(decryptedUser, decryptedPassword, addresses[i])

Of course you need to put async to those function as well.

Upvotes: 0

diferno
diferno

Reputation: 114

I just started playing with apigateway / lambda and sequelize, but as far as I know of node and sequelize, the callback should be inside the "then" block.

Yesterday found that if you're using callback(null, successData), the performance was really poor (>11 secs on a Select top 1). Had to change the flag context.callbackWaitsForEmptyEventLoop = false and now the api call takes 24ms.

    //Important to improve performance! 
    context.callbackWaitsForEmptyEventLoop = false

    // Find the device ID from the devices table
    models.Device.findOne({where: {device_uuid: body.device_uuid}, attributes: ['id']}).then(function(device) {
        console.log("During");

        // Make sure that we got a device back
        if (device === null) {
            callback(new Error("Device not found - could not insert data"))
        }
        else {
            console.log("Device found, inserting data - " + body.device_uuid);

            //Insert the data for this device
            models.Data.create({
               device_id: device.id,              
               data: body.data
            })
            .then(function(insertedData){
               callback(null, insertedData.toJSON())     
            })
            .catch(function(error){ 
                callback( new Error("Error creating")
            })
        }
    })    
    console.log("After")
}

Upvotes: 4

Related Questions