0

Here is my humble NodeJS function that times out after 5 minutes. CloudWatch Logs don't give me any details on what happened, just the it timed out.

const AWS = require('aws-sdk');
const util = require('util');
const simpleParser = require('mailparser').simpleParser;
const s3 = new AWS.S3();

exports.handler = async (event, context, callback) => {
    const srcBucket = event.Records[0].s3.bucket.name;
    const srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));

    const params = {
        Bucket: srcBucket,
        Key: srcKey
    };
    console.log(params)
    var data = await s3.getObject(params).promise();
    console.log(data)

};

Execution Env Node 12, 5 min timeout. I have verified the correct s3 trigger input and that the code works on my local nodeJS environment.

In execution role, I have added pretty much everything but the kitchen sink - AmazonRDSFullAccess AmazonS3FullAccess CloudWatchLogsFullAccess AmazonRDSDataFullAccess AmazonVPCFullAccess AWSLambdaExecute AWSLambdaVPCAccessExecutionRole AWS managed policy

any help is greatly appreciated, losing my mind at this point.

  • Almost certainly because you have deployed the Lambda function into a VPC, so it no longer has network access to S3. See the answer here: https://stackoverflow.com/questions/54112422/access-aws-s3-from-lambda-within-default-vpc This is a network configuration issue, not an IAM issue, so adding all those IAM execution roles are pointless. If it was an IAM issue you would get permission errors, not timeouts. – Mark B Apr 09 '20 at 23:51
  • I supposed you should include your secretKey and accessKey when declaring ```const s3 = new S3({ region: Config.get('aws.S3.region'), accessKeyId: Config.get('aws.accessKeyId'), secretAccessKey: Config.get('aws.secretAccessKey'), apiVersion: Config.get('aws.S3.apiVersion'), });``` object. – xion Apr 10 '20 at 01:26
  • What did you seen in the CloudWatch? `console.log(data)` has been executed, right? – hoangdv Apr 10 '20 at 03:23
  • @xion it is already picking up the Lambda function's IAM role. There is no need to do that. That is actually an anti-pattern. – Mark B Apr 10 '20 at 12:31
  • This is what I thought too, but when I removed it from the code itself, it won't work though. Not too sure why is that :/ – xion Apr 10 '20 at 12:55

1 Answers1

0

Because your lambda syntax is misleading. The problem is, you are using both callback and async. To use async properly, remove the callback from the parameters.

exports.handler = async (event) => {

  try {
    const srcBucket = event.Records[0].s3.bucket.name;
    const srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));

    const params = {
      Bucket: srcBucket,
      Key: srcKey
    };
    console.log(params)
    var data = await s3.getObject(params).promise();
    console.log(data)
  } catch (err) {
    console.log(err)
  }
};

AWS lambda still supports callback style handlers. Therefore your syntax is not incorrect. But if you have callback defined, the callback should be called at the end of the execution of the function.

You are getting the timeout since the callback is not called within the configured timeout period for the function (in this case 5 minutes).

here is the callback version.

exports.handler = async (event, context, callback) => {

  try {
    const srcBucket = event.Records[0].s3.bucket.name;
    const srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));

    const params = {
      Bucket: srcBucket,
      Key: srcKey
    };
    console.log(params)
    var data = await s3.getObject(params).promise();
    callback(null, 'completed successfully')
  } catch (err) {
    console.log(err)
    callback(err)
  }
};

hope this helps.

Arun Kamalanathan
  • 8,107
  • 4
  • 23
  • 39
  • I am afraid the problem is something else . It appears the function gets stuck at `await s3.getObject(params).promise()` . In my function, I tried to connect to RDS and that part seems to work if I skip the S3 call. ` const items = await db.select('*').from('processed_logs2').limit(5);` `console.log(items)` Thank you ! – vineet agarwal Apr 09 '20 at 23:05
  • You are getting a timeout after 5 minutes. That tells us that the lambda is waiting for something. So I strongly feels that I am right ;). Please use a try/catch to see if you can find the actual error. – Arun Kamalanathan Apr 09 '20 at 23:13
  • I tried your suggestion, I removed `callback` and `context` both. Still, same behavior. The try-catch block also isn't giving any errors, just the timeout thing again :( . I will try running it for 10 mins with try-catch to see if I can catch the error. – vineet agarwal Apr 09 '20 at 23:59
  • can you try my callback version of the code? please let me know the outcome – Arun Kamalanathan Apr 10 '20 at 03:16