Node Lambda times out when I query MySQL and try to send an email via AWS SES

aws

#1

I have the following node code

'use strict';
var aws = require('aws-sdk');
var async = require('async');
const mysql = require('mysql');

var ses = new aws.SES({
  region: 'eu-west-1'
});

module.exports.helloWorld = function(event, context, callback) {
  context.callbackWaitsForEmptyEventLoop = false;
  let connection = mysql.createConnection({
    host: "xxx",
    user: "xxx",
    password: "xxx",
    database: "xxx"
  });
  connection.query(`SELECT * FROM User U WHERE id = 1`, function(error, row) {
    let eParams = {
      Destination: {
        ToAddresses: [row[0].email]
      },
      Message: {
        Body: {
          Html: {
            Data: "Test"
          },
          Text: {
            Data: "Test"
          }
        },
        Subject: {
          Data: "Test Email"
        }
      },
      Source: "team@hello.com"
    };
    console.log('===SENDING EMAIL===');
    var email = ses.sendEmail(eParams, function(err, data) {
      if(err) {
        console.log(err);
        context.fail(err);
      } else {
        console.log("===EMAIL SENT===");
        console.log("EMAIL CODE END");
        console.log('EMAIL: ', email);
        console.log(data);
        context.succeed(event);
      }
    });
  });
}

Note: My SES default limits are removed.

This code always times out. My cloud watch log

{
  "errorMessage": "2018-01-19T11:58:16.794Z cc9e6998-fd0f-11e7-ae0a-xxxx Task timed out after 100.06 seconds"
}

START RequestId: cc9e6998-fd0f-11e7-ae0a-xxxx Version: $LATEST
2018-01-19T11:56:37.027Z	cc9e6998-fd0f-11e7-ae0a-xxxx	===SENDING EMAIL===
END RequestId: cc9e6998-fd0f-11e7-ae0a-xxxx
REPORT RequestId: cc9e6998-fd0f-11e7-ae0a-xxxx	Duration: 100057.09 ms	Billed Duration: 100000 ms 	Memory Size: 512 MB	Max Memory Used: 53 MB	
2018-01-19T11:58:16.794Z cc9e6998-fd0f-11e7-ae0a-xxxx Task timed out after 100.06 seconds

My Serverless config.

service: test
provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  region: eu-west-1
  memorySize: 512
  timeout: 100
  iamRoleStatements:
    - Effect: Allow
      Action:
        - s3:*
        - SNS:Publish
        - SES:SendRawEmail
        - SES:SendEmail
        - lambda:InvokeFunction
      Resource: "*"
  environment:
    NODE_ENV: live
  vpc:
    securityGroupIds:
      - sg-xxx
      - sg-xxx
      - sg-xxx
      - sg-xxx
    subnetIds:
      - subnet-xxx
      - subnet-xxx
      - subnet-xxx
functions:
  emailEmailFeedback:
    handler: handler.helloWorld
    events:
      - http:
          path: user-feedback
          method: get
          cors: true

Note: The VPC config is for my MySQL connection. I only have one VPC and all my services are within it.

When I take out the MySQL query and just run my SES test email, the function runs successfully.

Also, when I take the SES out and just run the MySQL I get the results back successfully.

But they don’t work together.

I also tried to move the SES to another function and tried to invoke the sendEmail function from inside my MySQL query callback, it didn’t work and I get the same timeout error.

lambda.invoke({
            FunctionName: 'sendEmail',
            Payload: JSON.stringify(rows, null, 2) // pass params
        }, function(error, data) {
            if (error) {
                context.fail({"hello": "world"});
            }
            if(data.Payload){
                context.succeed({"hello": "world"});
            }
        });

Any help would be much appreciated.

The question is also posted here,


#3

Hi Karthik,

It looks like your Lambda function doesn’t have Internet access.
Lambda is trying to access SES API and it timeouts before SES API connection timeout occurred - this is why you don’t get any error.

By default Lambdas in VPC don’t have Internet access. You need to add NAT Gateway or NAT Instance to your VPC.

Below article can help you configure VPC for Lambda with Internet Access:
https://aws.amazon.com/premiumsupport/knowledge-center/internet-access-lambda-function/

I hope this will help you!