Reputation: 7
I tried to import data from a csv file stocked in S3, and put the data in DynamaDB table. In my Lambda function which is in node.js, everything works fine, my data is well exported.
I tried to see if it was a problem with my Item, so I put the var params at the begining of the function (before the s3.getObjet) and the data was put in my dynamoDB table. Also, I tried to see if my problem was my if, but no console.log works fine in the if. I think, the only problem is my code, and I think it's a scope problem ?
var AWS = require("aws-sdk"),
documentClient = new AWS.DynamoDB.DocumentClient();
var s3 = new AWS.S3();
exports.handler = function(event, context, callback) {
var src_bkt = event.Records[0].s3.bucket.name;
var src_key = event.Records[0].s3.object.key;
var file;
var lignea;
// Retrieve the object
s3.getObject({
Bucket: src_bkt,
Key: src_key
}, function(err, dataFile) {
if (err) {
console.log(err, err.stack);
callback(err);
} else {
file = dataFile.Body.toString('ascii');
var rows = file.split('\n');
for(var i in rows){
lignea = rows[i].split(';');
if(lignea[2].startsWith('/France/Toulouse/')){
console.log("hey");
var params = {
Item : {
"ASSETTAG" : 'c',
"MAINHOST" : 'c'
},
TableName : process.env.TABLE_NAME
};
documentClient.put(params, function(err, data){
callback(err, data);
});
}
}
}
});
};
Edit : With help, my async code is like this :
var AWS = require("aws-sdk"),
documentClient = new AWS.DynamoDB.DocumentClient();
var s3 = new AWS.S3();
exports.handler = async function(event, context, callback) {
var src_bkt = event.Records[0].s3.bucket.name;
var src_key = event.Records[0].s3.object.key;
var file;
var lignea;
try{
// Retrieve the object
const dataFile = s3.getObject({
Bucket: src_bkt,
Key: src_key
}).promise();
file = dataFile.Body.toString('ascii');
var rows = file.split('\n');
for(var i in rows){
lignea = rows[i].split(';');
if(lignea[2].startsWith('/France/Toulouse/')){
console.log("hey");
var params = {
Item : {
"ASSETTAG" : 'test1',
"MAINHOST" : 'test2'
},
TableName : process.env.TABLE_NAME
};
await documentClient.put(params).promise();
}
}
}catch(e){
console.error("FAIL");
}
};
Thank you for your help !
Upvotes: 0
Views: 637
Reputation: 2198
You're right, it's a scope problem because you're calling an async function within a for loop. You could rewrite it like this, I believe:
function putDocument (params) {
return function() { documentClient.put(params, callback) };
}
for(var i in rows){
lignea = rows[i].split(';');
if(lignea[2].startsWith('/France/Toulouse/')){
console.log("hey");
var params = {
Item : {
"ASSETTAG" : 'c',
"MAINHOST" : 'c'
},
TableName : process.env.TABLE_NAME
};
putDocument(params);
}
}
You could also try using let
when defining params
as it'll have the correct scope or use .forEach
to create a closure.
Upvotes: 0
Reputation: 412
Two things I noticed
you should use a package like "async"
var AWS = require("aws-sdk"),
documentClient = new AWS.DynamoDB.DocumentClient();
var s3 = new AWS.S3();
var async = require("async")
exports.handler = function(event, context, callback) {
var src_bkt = event.Records[0].s3.bucket.name;
var src_key = event.Records[0].s3.object.key;
var file;
var lignea;
// Retrieve the object
s3.getObject({
Bucket: src_bkt,
Key: src_key
}, function(err, dataFile) {
if (err) {
console.log(err, err.stack);
return callback(err);
}
var things_to_insert = []
file = dataFile.Body.toString('ascii');
var rows = file.split('\n');
for(var i in rows){
lignea = rows[i].split(';');
if(lignea[2].startsWith('/France/Toulouse/')){
console.log("hey");
var params = {
Item : {
"ASSETTAG" : lignea[0], // this must be your partition key
"MAINHOST" : lignea[1] // this must be your sort key
},
TableName : process.env.TABLE_NAME
};
things_to_insert.push(params)
}
}
async.forEachOf(things_to_insert, function(params, key, cb ) {
documentClient.put(params, function(err, data){
cb(err, data);
});
}, function(err) {
callback(err) // called only once at the end
})
});
};
Upvotes: 0
Reputation: 10882
You're actually calling handler's callback when a first put result comes, which results to the immediate end of process.
Try these changes:
exports.handler = async function
This enables async/await mechanism of dealing with async code.
await documentClient.put(params).promise();
Almost all AWS methods have this variant returning a Promise
instead of using a callback. await
syntax wait for a Promise result in synchronous manner.
const dataFile = await s3.getObject({
Bucket: src_bkt,
Key: src_key
}).promise();
Remove callbacks whatsoever.
Close the whole handler into a try/catch
block.
Upvotes: 1