4 votes

Délai d'attente du processus entre Amazon Lambda et Firebase

J'ai écrit du code en node.js et mes données sont sur Firebase. Le problème auquel je suis confronté est que mon code ne sort jamais. Je l'ai fait comme ceci Lien

Le problème est que le référent/auditeur de firebase ne devient jamais nul et donc ma fonction ne se termine jamais. J'ai essayé d'utiliser firebase.database().goOffline() mais ça n'a pas marché.

Sur ma machine locale, j'ai arrêté de force le processus en utilisant process.exit(0) mais lorsque j'ai déployé mon code sur AWS lambda, il ne renvoie pas de réponse/appel et se termine (en donnant le message d'erreur " Le processus s'est arrêté avant de terminer la demande ")

J'ai également ajouté une attente de 5 à 10 secondes après avoir invoqué le callback dans le lambda, puis j'ai quitté le processus de force, mais cela n'a pas aidé non plus.

Comment résoudre ce problème ? Veuillez nous aider.

8voto

johni Points 816

Vous traversez une crise que toute nouvelle lambda L'utilisateur est parti.

Comme suggéré, vous pouvez utiliser context.done pour s'arrêter. Cependant Il n'est pas recommandé de le faire, car cela n'est possible qu'en raison des versions d'exécution historiques de nodejs.


pourquoi ce délai d'attente se produit-il ?

Votre lambda peut arriver à la dernière ligne de votre code et continuer à fonctionner. En fait, il attend quelque chose - que la boucle d'événements soit vide.

ce que cela signifie ?

Dans nodejs, lorsque vous effectuez une opération asynchrone et enregistrez une fonction de rappel à exécuter une fois l'opération terminée, l'enregistrement se fait en quelque sorte dans la boucle d'événement.

En une ligne, c'est la boucle d'événements qui sait quelle fonction de rappel exécuter à la fin d'une opération asynchrone. Mais c'est un autre sujet :)


Retour à Lambda

Compte tenu des informations ci-dessus, il s'ensuit que lambda ne devrait pas s'arrêter avant que la boucle d'événement vide ne soit atteinte - car cela implique une procédure de suivi ne sera pas s'exécuter après le retour d'une opération asynchrone.

Que faire si vous avez toujours besoin d'arrêter l'exécution manuellement, quel que soit l'état de la boucle d'événement ? Au début de la fonction, exécutez :

context.callbackWaitsForEmptyEventLoop = false

Et ensuite utiliser le troisième paramètre que vous obtenez dans la signature du handler. Qui est le callback .

le paramètre de rappel

C'est une fonction que vous appelez lorsque vous voulez terminer l'exécution.

Si vous l'appelez sans paramètres, ou avec le premier paramètre comme null et le texte comme second paramètre, l'appel est considéré comme une invocation réussie.

Pour faire échouer l'exécution de la lambda, vous pouvez appeler la fonction de rappel avec une valeur non nulle comme premier paramètre.

4voto

idbehold Points 12445

Ajoutez cette ligne au début de votre fonction de gestion et vous devriez pouvoir utiliser la fonction de rappel sans problème :

function handler (event, context, callback) {
  context.callbackWaitsForEmptyEventLoop = false // Add this line
}

1voto

Fayza Nawaz Points 1002

Appel à callback et ensuite process.exit(0) n'a pas aidé dans mon cas. goOffline() méthode de firebase n'a pas aidé non plus.

J'ai réglé le problème en appelant context.done(error, response) (au lieu de la méthode callback). Maintenant, mon code fonctionne.

Cependant, si quelqu'un a une meilleure solution, veuillez la poster ici. Cela pourrait aider quelqu'un d'autre :)

1voto

gchao Points 170

Réglage de callbackWaitsForEmptyEventLoop a false ne devrait être que votre dernier recours si rien d'autre ne fonctionne pour vous, car cela pourrait introduire des bogues pires que le problème que vous essayez de résoudre ici.

C'est ce que je fais à la place pour m'assurer que chaque appel a initialisé firebase, et supprimé avant de sortir.

// handlerWithFirebase.js

const admin = require("firebase-admin");
const config = require("./config.json");

function initialize() {
  return admin.initializeApp({
    credential: admin.credential.cert(config),
    databaseURL: "https://<your_app>.firebaseio.com",
  });
}

function handlerWithFirebase(func) {
  return (event, context, callback) => {
    const firebase = initialize();
    let _callback = (error, result) => {
      firebase.delete();
      callback(error, result);
    }
    // passing firebase into your handler here is optional
    func(event, context, _callback, firebase /*optional*/);
  }
}

module.exports = handlerWithFirebase;

Et ensuite, dans mon code de gestion lambda

// myHandler.js

const handlerWithFirebase = require("../firebase/handler");

module.exports.handler = handlerWithFirebase(
(event, context, callback, firebase) => {
    ...
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X