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"});
}
タイプミスがあります:
context.callbackWaitsForEmtpyEventLoop = false;
する必要があります:
context.callbackWaitsForEmptyEventLoop = false;
以下は、 documentation がcallbackWaitsForEmptyEventLoopの動作について述べているものです。
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');
};
次のような新しい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);
}