4
votes

After completing the AWS Lambda tutorial for creating thumbnails, I decided to try and tweak the code to check if a file was a jpg or csv file and if it was simply move it to a new bucket. The only things I removed from my code were the comments and the function within the async.waterfall that would resize images. However, whenever I test or run this new code, I get "process exited before completing request" and the function does not transfer the files correctly. Here is the code:

var async = require('async');
var AWS = require('aws-sdk');
var gm = require('gm')
            .subClass({ imageMagick: true }); // Enable ImageMagick integration.
var util = require('util');






var s3 = new AWS.S3();

exports.handler = function(event, context) {

    console.log("Reading options from event:\n", util.inspect(event, {depth: 5}));
    var srcBucket = event.Records[0].s3.bucket.name;

    var srcKey    =
    decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));  
    var dstBucket = 'datacollectionbucket';
    var dstKey    = srcKey;


    if (srcBucket == dstBucket) {
        console.error("Destination bucket must not match source bucket.");
        return;
    }


    var typeMatch = srcKey.match(/\.([^.]*)$/);
    if (!typeMatch) {
        console.error('unable to infer file type for key ' + srcKey);
        return;
    }
    var imageType = typeMatch[1];
    if (imageType != "jpg" && imageType != "csv") {
        console.log('skipping unrecognized file ' + srcKey);
        return;
    }


    async.waterfall([
        function download(next) {
            s3.getObject({
                    Bucket: srcBucket,
                    Key: srcKey
                },
                next);

        function upload(contentType, data, next) {

            s3.putObject({
                    Bucket: dstBucket,
                    Key: dstKey,
                    Body: data,
                    ContentType: contentType
                },
                next);
            }
        ], function (err) {
            if (err) {
                console.error(
                    'Unable to resize ' + srcBucket + '/' + srcKey +
                    ' and upload to ' + dstBucket + '/' + dstKey +
                    ' due to an error: ' + err
                );
            } else {
                console.log(
                    'Successfully classified ' + srcBucket + '/' + srcKey +
                    ' and uploaded to ' + dstBucket + '/' + dstKey
                );
            }

            context.done();
        }
    );
};

Thanks guys

1
What are you getting in your log? You have quite a few console.log calls, how many of those are appearing in your log file? How far does the code get before exiting? - garnaat
None of my console.log calls are showing up, it simply tells me process exited before completing request - Fivehoursoffun
Well, then the script is exiting before your first call to console.log. Are you still bundling the same dependencies into the zip file (e.g. async and utils)? - garnaat
Yes I am, I have the correct dependencies and everything. I don't know if you're familiar with the original code, but this is just an edit of the code supplied by amazon for the "create thumbnail" tutorial, with two variables (which my edit doesn't call) and an image resizing function removed. However when I re add the image resizing function the "process exited" result still shows up. - Fivehoursoffun

1 Answers

0
votes

That means that you're not calling context.done() before returning from your function, or that your work isn't finishing within the lambda's timeout.

For the first possibility, you have several blocks of code like this in your example:

if (srcBucket == dstBucket) {
    console.error("Destination bucket must not match source bucket.");
    return;
}

Those all ought to be like this, instead:

if (srcBucket == dstBucket) {
    var errorText = "Destination bucket must not match source bucket."
    console.error(errorText);
    context.done(errorText);
    return;
}

If you pass any arguments to context.done(), then they assume the first one is an error. (If you have no errors, then simply call context.done() as you're already doing at the end of your waterfall).

So it's likely that one of these error cases is being hit but you're not receiving the error back out of lambda.

The other way this might happen is if the S3 getObject and putObject calls are taking longer than your lambda function's assigned timeout value. You can try raising it to the maximum 60 seconds in the "config" tab of the lambda function's settings to see if you start getting your responses.