One of the annoying things about software engineering is that working code doesn’t necessarily stay working. About eight years ago I wrote an Amazon Web Services Lambda Function using Node JS (I think version 10). Five years ago when the node version was end of life I updated it to Node 12 with no changes needed and it has been working ever since. I’ve had a few warnings from AWS about code relying on versions of node that are end-of-life but it was still working when I tested it.
exports.handler = (event, context, callback) => {
var s3Bucket = "my-bucket-name";
var key = "my-item-key";
var AWS = require('aws-sdk');
var s3 = new AWS.S3({region: 'eu-west-1'});
var getFromAWS = function() {
var params = {Bucket: s3Bucket, Key: key1};
s3.getObject(params, function(err, data) {
if(err) {
itemJson = "[\"Error\":[\"Key not found\"]]";
console.log(err, err.stack); // an error has happened on AWS
}
else {
itemJson = data.Body.toString('UTF8');
}
}
if (itemJson != "") {
callback (null, {"key":key1, "data":itemJson});
});
};
getFromAWS();
};
JavaScriptThis week I needed to make a minor change to it, but in order to so I needed to update it to a later version of Node. As soon as I did so I got the following error.
Error: Cannot find Module ‘aws-sdk’
A quick google confirmed the issue, aws-sdk is no longer bundled as standard with Node on AWS lambda. This is slightly annoying as there are plenty of even recent articles which use the var AWS = require(‘aws-sdk’) syntax.
After reading up on it I decided it was probably time to bring the module fully up to date. In order to do that I would need to use AWS SDK version 3. Firstly I needed to import the required modules, and secondly I needed to use a different syntax to do the s3 Get Object command
import {S3Client, GetObjectCommand} from '@aws-sdk/client-s3';
var s3 = new S3Client({region: 'eu-west-1'});
const response = s3.send(new GetObjectCommand({
Bucket: s3Bucket,
Key: key,
}));
JavaScriptUnfortunately as soon as I tried to make those changes I got a second error message.
Uncaught SyntaxError: Cannot use import statement outside a module
A quick search revealed that the simple solution to this is to ensure that the code was named index.mjs instead of index.js to show node that it was a module.
With these fixes in place I was able to rewrite the whole function.
Asynchronously Get Objects from S3 in parallel
I needed to be able to return two json files from S3. In order to keep the Lambda execution as short as possible I wanted to run the two commands in parallel. To achieve this I call the async getFromAWS function without using await, and then await both results in the highlighted line.
The full code of the working version is included below.
import {S3Client, GetObjectCommand} from '@aws-sdk/client-s3';
export const handler = async (event) => {
var s3Bucket = "my-bucket-name"";
var s3 = new S3Client({region: 'eu-west-1'});
const getFromAWS = async(key) => {
const r = await s3.send(new GetObjectCommand({
Bucket: s3Bucket,
Key: key,
}));
const json = await r.Body.transformToString();
return json;
};
var response;
try {
const firstJson = getFromAWS("my-item-key1");
const secondJson = getFromAWS("my-item-key2");
const result = [await firstJson, await secondJson];
response = {
"data1":JSON.parse(result[0]),
"data2":JSON.parse(result[1])};
} catch (e) {
console.log(e);
response = {"Error":"An Error Occurred"}
}
return response;
};
JavaScript
Leave a Reply