Reputation: 135
I am trying to invoke async lambda function from another lambda function with NodeJS. At the end, I will have 3 lambda function. 1. Function will ask for user list 2. Function will ask details for each user 3. Create a record for that user in DB
First request is working fine, I can get user list but I don't see any sign that second lambda has been invoked.
'use strict';
const AWS = require("aws-sdk");
const rp = require('request-promise');
const lambda = new AWS.Lambda({
region: "eu-central-1"
});
module.exports.getUserDetailsFromCrowd = async event => {
console.log("Get User Details Function")
var crowdUserDetailsOptions = {
"method": "GET",
"uri": event,
'auth': {
'user': process.env.user,
'pass': process.env.pass,
'sendImmediately': false
},
"json": true,
"headers": {
"Accept": "application/json"
}
}
return rp(crowdUserDetailsOptions).then(function (result) {
console.log(JSON.stringify(result))
}).catch(function (err) {
console.log(JSON.stringify(err))
})
};
module.exports.getUserListFromCrowd = async event => {
console.log("GetUserListFunction")
var crowdUserGroupOptions = {
"method": "GET",
"uri": process.env.uri,
'auth': {
'user': process.env.user,
'pass': process.env.pass,
'sendImmediately': false
},
"json": true,
"headers": {
"Accept": "application/json"
}
};
return rp(crowdUserGroupOptions)
.then(function (body) {
console.log("Request Sent")
const userList = body;
var userLinks = userList.users;
for (var i = 0; i < userLinks.length; i++) {
var requestLink = userLinks[i].link.href + "&expand=attributes"
console.log("Request: " + i)
console.log(requestLink)
const params = {
FunctionName: "applicationName-stageName-getUserDetailsFromCrowd",
InvocationType: "Event",
Payload: requestLink,
LogType: "Tail",
}
console.log("Calling Lambda")
lambda.invoke(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
console.log("Called Lambda")
}
})
.catch(function (err) {
console.log(JSON.stringify(err));
});
};
I got the log below:
2019-11-08T08:38:29.892Z 1da97723-f792-408a-b6dd-24c7d1b343d4 INFO Request: 9
2019-11-08T08:38:29.892Z 1da97723-f792-408a-b6dd-24c7d1b343d4 INFO https://aaa.com/user/details
2019-11-08T08:38:29.892Z 1da97723-f792-408a-b6dd-24c7d1b343d4 INFO Calling Lambda
2019-11-08T08:38:29.894Z 1da97723-f792-408a-b6dd-24c7d1b343d4 INFO Called Lambda
I am at least expecting to see something in between "Calling Lambda" and "Called Lambda" but nothing happens. Also, I don't see any log on the console for second function that shows it has been invoked.
Upvotes: 1
Views: 2853
Reputation: 82096
The Lambdas will be firing, the issue is you don't wait for the invocations to finish. Your Lambda is async
, but you don't actually use await
, and given the lambda.invoke
is an I/O bound call there is nothing in your code that would force the Lambda to wait for each invocation to finish.
Here's a way you can queue up the internal calls and make your Lambda wait for the results:
module.exports.getUserListFromCrowd = async event => {
console.log('GetUserListFunction')
const crowdUserGroupOptions = {
method: 'GET',
uri: process.env.uri,
auth: {
user: process.env.user,
pass: process.env.pass,
sendImmediately: false
},
json: true,
headers: {
Accept: 'application/json'
}
};
const { users } = await rp(crowdUserGroupOptions);
console.log('Request Sent')
const requests = users.map(u =>
new Promise((resolve, reject) => {
const url = `${u.link.href}&expand=attributes`;
const params = {
FunctionName: 'applicationName-stageName-getUserDetailsFromCrowd',
InvocationType: 'Event',
Payload: requestLink,
LogType: 'Tail',
}
console.log('Calling Lambda');
lambda.invoke(params, (err, data) => err ? reject(err) : resolve(data));
})
);
console.log(`Waiting for ${requests.length} requests to finish...`);
const results = await Promise.all(requests);
console.log('Lambda results');
results.forEach((x, i) => console.log(`Request ${i+1} returned ${x}`));
};
Upvotes: 2