1
votes

Scenario:

I have a Node.JS 12.x Lambda that is backing an Alexa Skill. The user asks the skill a question, and the search parameter is sent to my Lambda in a slot. I query the SQL DB using the mssql package, then return the result to the user.

Issue:

If I fetch results from the DB, the Lambda executes the query successfully and returns the result, but then the Lambda times out and Alexa seems to have not received the response. If I remove the DB query and just return a string, it all works just fine.

Suspicions:

I think there may be some issue with the async/await stuff in here. I just can't figure out what the issue is though. I have checked my use of async/await several times

If I left anything out just let me know. Thanks in advance!

Code:

/**
 * Intent handler for FindSomething intent
 */
const MyHandler = {
    /**
     * Determine whether this handler is able to process this input
     * @param {Object} handlerInput The input object
     */
    canHandle(handlerInput) {
        // This part works fine
        return util.checkIntentMatch(handlerInput, INTENT_NAME);
    },

    /**
     * Handle the input
     * @param {Object} handlerInput The input object
     */
    async handle(handlerInput) {
        // Extract slot values
        const [
            searchTerm,
        ] = [
            Alexa.getSlotValue(handlerInput.requestEnvelope, 'search_term'),
        ];

        // Fulfill request
        const responseText = await getResponseText(searchTerm);

        // Respond
        return handlerInput.responseBuilder
            .speak(responseText)
            .getResponse();
    },
};

And then getResponseText looks like this:

/**
 * Get the response text for the query
 * @param {string} searchTerm The search term from the user
 */
async function getResponseText(searchTerm) {
    let sectorName = await getSectorForTerm(searchTerm);
    console.log(`Inside getResponseText.  sectorName: ${sectorName}`);

    if (!sectorName) return format(NOT_FOUND_LANGUAGE, { searchTerm });

    return format(FOUND_LANGUAGE, { searchTerm, sectorName });
}

/**
 * Find the sector for a search term
 * @param {string} searchTerm The search term from the user
 */
async function getSectorForTerm(searchTerm) {

    // ========================================================================
    // If I uncomment this line, it works great -- all the way back to the user
    // ========================================================================
    //return 'fake result';

    // Gather prerequisites in parallel
    let [
        query,
        pool
    ] = await Promise.all([
        fs.readFile(path.join(__dirname, 'queries', 'FindQuery.sql'), 'utf8'),
        sql.connect(process.env['connectionString'])
    ]);

    console.log('Pre query');

    // Run query
    let queryResult = await pool.request()
        .input('EntityName', sql.TYPES.VarChar, searchTerm)
        .query(query);

    console.log('Post query');

    // Extract result if any
    let result = undefined;
    if(queryResult.recordset.length > 0) {
        result = queryResult.recordset[0]['SectorName'];
    }

    console.log(`result of getSectorForTerm: ${result}`);

    return result;
}

Edit:

Here is what the log looks like. You can see that the file has loaded, the query has executed, and the return statement is hit within ~500ms. Then several seconds pass before the function times out.

CloudWatch Logs Example

Edit 2:

I have structured my index.js like this example from the AWS docs, so I don't have direct access to context or similar. That can be changed if needed.

enter image description here

1

1 Answers

0
votes

You are using 2 time consuming operations in your skill - file read and sql connection. Probably your skill exceeds 8s timeout. Please check CloudWatch logs related to your skill if there is message like

Task timed out after 8.01 seconds

you should work on some enhancements here. Also make sure that both methods in Promise.all argument return a Promise.