1

This is my first question ever here:-)

I need to list users in our Cognito use pool. Seems this can be done only using the aws-sdk CognitoIdentityServiceProvider APIs. I got the below code to work perfectly from my local node.js. It lists all users as expected.

However, the same code behaves differently when put into an AWS lambda function. It still runs, but it never waits for the Cognito listUsers() call to return. It just simply completes, like the "await" is not waiting at all. None of the console.log() is invoked from the client.listUsers(params, function(err, data)..._ block.

I tested this inside Lambda directly as well as from AWS API gateway. The same null is return. The call itself is successful, just no data is returned. See log at the end.

BTW, I did create a role and add a policy giving the role full access to the cognito user pool.

What did I miss? Appreciate your help!

Martin C.

-----------------code------------------------

async function getUserList() {
    console.log("enter LAMDA function**********");
    var aws = require('aws-sdk');
    aws.config.update({accessKeyId: 'xxxxxxxx', secretAccessKey: 'xxxxxxxxxxx'});
    var CognitoIdentityServiceProvider = aws.CognitoIdentityServiceProvider;
    var client = new CognitoIdentityServiceProvider({ apiVersion: '2016-04-19', region: 'us-east-2' });

    var params = {
         UserPoolId: 'us-east-xxxxxxxx', /* required */
          AttributesToGet: [
          'given_name','family_name','phone_number','email','profile'
        ],
        Filter: null,
        Limit: 0,
        PaginationToken: null
    };
    console.log("Right before call the listUser method");

    let result = await client.listUsers(params, function(err, data) {
     console.log("call back reached!");
     if (err) { 
              console.log(err, err.stack); // an error occurred
              const response = {
              statusCode: 500,
              body: JSON.stringify('An error occurred.'),
        }
        return response;
     }
     else  {
         console.log(data);   
         var count = data.Users.length;
             // successful response
             const response = {
             statusCode: 200,
             body: JSON.stringify("sucessful list users! User count="+count)
          }
          return response;
     }
    });

    console.log("no waiting here. async!!!")
}

getUserList();

***************Lambda log*****************

Log when called from Lambda

**************Log when called from node.js****************

Log when called from node.js

Siong Thye Goh
  • 3,518
  • 10
  • 23
  • 31
Martin C
  • 51
  • 6

1 Answers1

2

getUserList is your lambda function? I don't know why you call it by your self getUserList().

I see, you are using lambda runtime is nodejs version > 8, you use await keyword with a callback function(fail) => you not wait anything.

When a function call by Lambda, the function (async function) will finish when get a return or run to end of function (without return), in your case the function finish when console.log("no waiting here. async!!!") has been executed. In local environment, the funciton finishs when callstack has been clear (do not have any callback function in callstack).

Right way, you have use promise version of aws-sdk then use await syntax to get a result. Relate to How to use Async and Await with AWS SDK Javascript

async function getUserList() {
    console.log("enter LAMDA function**********");
    var aws = require('aws-sdk');
    aws.config.update({ accessKeyId: 'xxxxxxxx', secretAccessKey: 'xxxxxxxxxxx' });
    var CognitoIdentityServiceProvider = aws.CognitoIdentityServiceProvider;
    var client = new CognitoIdentityServiceProvider({ apiVersion: '2016-04-19', region: 'us-east-2' });

    var params = {
        UserPoolId: 'us-east-xxxxxxxx', /* required */
        AttributesToGet: [
            'given_name', 'family_name', 'phone_number', 'email', 'profile'
        ],
        Filter: null,
        Limit: 0,
        PaginationToken: null
    };
    console.log("Right before call the listUser method");

    try {
        let result = await client.listUsers(params).promise(); // use Promise style
        console.log(data);
        var count = data.Users.length;
        // successful response
        const response = {
            statusCode: 200,
            body: JSON.stringify("sucessful list users! User count=" + count)
        }
        return response; // return to finish function
    } catch (err) {
        console.log(err, err.stack); // an error occurred
        const response = {
            statusCode: 500,
            body: JSON.stringify('An error occurred.'),
        }
        return response;
    }
}

getUserList(); // remove this line when deploy funtion to Lambda.
hoangdv
  • 15,138
  • 4
  • 27
  • 48
  • Indeed, the promise type works! Thanks so much! BTW, getUserList() is just how I invoke the async function from node.js. The body of getUserList() goes to the lambda function. – Martin C Mar 03 '19 at 13:45