web-dev-qa-db-ja.com

AWS Lambda機能が常にタイムアウトするのはなぜですか?

4.3のバージョンでnodejsを使用して、aws lambdaをテストしています。コンソールテスト内のハンドラー関数内のすべてのステートメントを正常に完了することができます。これには、vpc内のmongodbホストへの接続が含まれます。ただし、関数は常にタイムアウトします。コールバックの使用、コンテキストのプロパティの設定、IAMロールのアクセス許可について説明するいくつかの投稿とリソースを見つけましたが、何をしても、常にタイムアウトになります。現在のコード:

'use strict';

var Mongoose = require('mongoose');
var Device = require('./device_model');
var Alarm = require('./alarm_model');
var Event = require('./event_model');

var mongoConnection = process.env.MONGO_URL;

var connection = Mongoose.connect(mongoConnection);

Mongoose.connection.once('open', function() {
    console.log("Connecting to mongo at: " + mongoConnection);
    console.log("Mongoose connection in lambda opened");
});

Mongoose.connection.on('error', function(){
    console.error("Error creating mongoose connection in lambda, exiting!");
    process.exit(1);
});

exports.check_alarms = function(event, context, callback) {

    context.callbackWaitsForEmtpyEventLoop = false;
    console.log("The incoming event: " + JSON.stringify(event));

    var device = null;
    Device.findByUUID(event.uuid, function(error, result){
        if(!error){
            device = result;
            console.log("the device: " + JSON.stringify(device));
            if(event.Ale && event.Ale.length > 0) {
                console.log("We have an alarm, checking if already set");
                callback(null, {"status":"alarms"});
            } else {
                console.log("Event contains no alarm; checking for historic active");
                callback(null, {"status":"no alarms"});
            }
        } else {
            console.log("there's a problem on mongo");
            callback("problem", "status not so good");
        }
    });

    callback(null, {"status":"outside of device find block"});
}
13
wkhatch

タイプミスがあります:

context.callbackWaitsForEmtpyEventLoop = false;

する必要があります:

context.callbackWaitsForEmptyEventLoop = false;

以下は、 documentationcallbackWaitsForEmptyEventLoopの動作について述べているものです。

callbackWaitsForEmptyEventLoop

デフォルト値はtrueです。このプロパティは、コールバックのデフォルトの動作を変更する場合にのみ役立ちます。デフォルトでは、コールバックはNode.jsランタイムイベントループが空になるまで待機してからプロセスをフリーズし、結果を呼び出し元に返します。このプロパティをfalseに設定すると、イベントループにイベントがある場合でも、コールバックが呼び出された直後にプロセスをフリーズするようAWS Lambdaにリクエストできます。 AWS Lambdaは、Node.jsイベントループ内のプロセス、状態データ、およびイベントを凍結します(イベントループ内の残りのイベントは、Lambda関数が次に呼び出され、AWS Lambdaが凍結プロセスの使用を選択した場合に処理されます)。コールバックの詳細については、 コールバックパラメータの使用 を参照してください。

最小限の例:

// Times out due to typo
exports.function1 = (event, context, callback) => {
    setInterval(() => console.log('Long wait'), 100000);
    context.callbackWaitsForEmtpyEventLoop = false;
    callback(null, 'Hello from Lambda');
};

// Returns successfully
exports.function2 = (event, context, callback) => {
    setInterval(() => console.log('Long wait'), 100000);
    context.callbackWaitsForEmptyEventLoop = false;
    callback(null, 'Hello from Lambda');
};
24
wjordan

次のような新しいAlexaプロジェクトにcallbackWaitsForEmptyEventLoopを追加する方法について私と同じように誰かが混乱した場合:

const skillBuilder = Alexa.SkillBuilders.custom();

exports.handler = skillBuilder
  .addRequestHandlers(
      GetNewFactHandler,
      HelpHandler,
      ExitHandler,
      FallbackHandler,
      SessionEndedRequestHandler,
  )
  .addRequestInterceptors(LocalizationInterceptor)
  .addErrorHandlers(ErrorHandler)
  .lambda();

ここにあるプロジェクト例: https://github.com/Alexa/skill-sample-nodejs-fact/blob/master/lambda/custom/index.js

このソリューションは私のために働いた:

// create a custom skill builder
const skillBuilder = Alexa.SkillBuilders.custom();

exports.handler = (event, context, callback) => {
  // we need this so that async stuff will work better
  context.callbackWaitsForEmptyEventLoop = false

  // set up the skill with the new context
  return skillBuilder
    .addRequestHandlers(
      GetNewFactHandler,
      HelpHandler,
      ExitHandler,
      FallbackHandler,
      SessionEndedRequestHandler,
    )
    .addRequestInterceptors(LocalizationInterceptor)
    .addErrorHandlers(ErrorHandler)
    .lambda()(event, context, callback);
}
3
tdon