it-roy-ru.com

Почему функция AWS Lambda всегда истекает?

Я тестирую AWS лямбда, используя nodejs с версией 4.3. Я могу успешно выполнить все операторы в своей функции обработчика в тесте консоли, который включает в себя подключение к хосту mongodb в нашем vpc. Но функция всегда отключается. Я нашел несколько постов и ресурсов, в которых обсуждается использование обратного вызова и настройка свойств для контекста и разрешений роли 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"});
}
10
wkhatch

У вас есть опечатка:

context.callbackWaitsForEmtpyEventLoop = false;

должно быть:

context.callbackWaitsForEmptyEventLoop = false;

Вот что документация говорит о поведении 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');
};
15
wjordan

Если кто-то запутался, как я, с тем, как добавить callbackWaitsForEmptyEventLoop в новые проекты Alexa, которые выглядят так:

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);
}
1
tdon