web-dev-qa-db-fra.com

Pourquoi la fonction AWS Lambda expire-t-elle toujours?

Je teste aws lambda, en utilisant nodejs avec la version 4.3. Je suis en mesure de terminer avec succès toutes les instructions de ma fonction de gestionnaire dans le test de la console, ce qui inclut la connexion à un hôte mongodb dans notre vpc. Mais, la fonction expire toujours. J'ai trouvé plusieurs publications et ressources qui traitent de l'utilisation du rappel et de la définition des propriétés sur le contexte et des autorisations de rôle IAM, mais quoi que je fasse, le délai d'attente est toujours dépassé. Code actuel:

'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

Vous avez une faute de frappe:

context.callbackWaitsForEmtpyEventLoop = false;

devrait être:

context.callbackWaitsForEmptyEventLoop = false;

Voici ce que la documentation dit sur le comportement de callbackWaitsForEmptyEventLoop:

callbackWaitsForEmptyEventLoop

La valeur par défaut est true. Cette propriété est utile uniquement pour modifier le comportement par défaut du rappel. Par défaut, le rappel attendra que la boucle d'événements d'exécution Node.js soit vide avant de geler le processus et de renvoyer les résultats à l'appelant. Vous pouvez définir cette propriété sur false pour demander à AWS Lambda de geler le processus peu de temps après l'appel du rappel, même s'il existe des événements dans la boucle d'événements. AWS Lambda gèlera le processus, toutes les données d'état et les événements de la boucle d'événements Node.js (tous les événements restants de la boucle d'événements traités lors du prochain appel de la fonction Lambda et si AWS Lambda choisit d'utiliser le processus gelé). Pour plus d'informations sur le rappel, voir Utilisation du paramètre de rappel .

Exemple minimal:

// 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

Si quelqu'un était confus, comme moi, avec la façon d'ajouter callbackWaitsForEmptyEventLoop à de nouveaux projets Alexa qui ressemblent à ceci:

const skillBuilder = Alexa.SkillBuilders.custom();

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

Exemple de projet trouvé ici: https://github.com/Alexa/skill-sample-nodejs-fact/blob/master/lambda/custom/index.js

Cette solution a fonctionné pour moi:

// 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