web-dev-qa-db-fra.com

invoquer aws lambda d'un autre lambda de manière asynchrone

J'ai besoin d'invoquer aws lambda à partir d'un autre lambda de manière asynchrone. j'ai un code de travail pour les appels synchrones.

exports.handler = (event, context, callback) => {
    var aws = require('aws-sdk');
    var lambda = new aws.Lambda({
        region: 'myregion' //change to your region
    });
    console.log("lambda invoke started");
    lambda.invoke({
        FunctionName: 'testLambda',
        Payload: JSON.stringify(event, null, 2) // pass params
    }, function (error, data) {
        if (error) {
            console.log("error");
            callback(null, 'hello world');
        }
        else {
            console.log("lambda invoke end");
            callback(null, 'hello world');
        }
    });
}

Mais dans mon cas, "testLambda" est une fonction qui prend du temps. Parce que je dois quitter juste après avoir invoqué la fonction 'testLambda'. Ensuite, le code est mis à jour comme ceci

exports.handler = (event, context, callback) => {
    var aws = require('aws-sdk');
    var lambda = new aws.Lambda({
        region: 'myregion' //change to your region
    });
    console.log("lambda invoke started");
    lambda.invoke({
        FunctionName: 'testLambda',
        Payload: JSON.stringify(event, null, 2) // pass params
    });
    console.log("lambda invoke end");
    callback(null, 'hello world');
}

il renvoie correctement le message. Mais ma fonction 'testLambda' n'est pas invoquée (aucun journal de surveillance cloud n'est généré pour le test lambda). quel est le problème lié à ce code.

17
Abdul Manaf

Par la documentation Lambda invoke () , vous verrez que par défaut la fonction Lambda est invoquée en utilisant le type d'invocation RequestResponse. Pour appeler la fonction de manière asynchrone, vous devez spécifier le type d'invocation Event, comme suit:

lambda.invoke({
    FunctionName: 'testLambda',
    InvocationType: 'Event',
    Payload: JSON.stringify(event, null, 2)
},function(err,data){});
16
Mark B

Je travaillais avec la dernière version node.js 8.1 actuellement dans AWS Lambda.
Le deuxième lambda ne s'est pas exécuté (et la fonction de rappel n'a jamais été appelée) jusqu'à ce que j'utilise le asynchrone/attendre mécanisme.
La fonction de gestionnaire doit donc être asynchrone et l'appel 'lambda.invoke' doit être entouré d'un Promise .

voici mon code de travail:

function invokeLambda2(payload) {
    const params = {
        FunctionName: 'TestLambda2',
        InvocationType: 'Event',
        Payload: JSON.stringify(payload)
    };

    return new Promise((resolve, reject) => {

        lambda.invoke(params, (err,data) => {
            if (err) {
                console.log(err, err.stack);
                reject(err);
            }
            else {
                console.log(data);
                resolve(data);
            }
        });     
    });
}


exports.handler = async (event, context) => {
    const payload = {
        'message': 'hello from lambda1'
    };
    await invokeLambda2(payload);
    context.done();
};

Veuillez noter que le gestionnaire n'attend pas que le deuxième lambda se termine, seulement pour qu'il soit déclenché et que la fonction de rappel soit appelée.

Vous pouvez également retourner le Promise depuis le gestionnaire, ne pas avoir à utiliser attendez avec une deuxième fonction.

Pas besoin d'importer lorsque vous travaillez avec Promises et async/wait, autre que:

const AWS = require('aws-sdk');
const lambda = new AWS.Lambda();
10
ronginat

Voilà comment j'utilise dans Express.js


var express = require("express");
var router = express.Router();

const asyncMiddleware = fn =>
  (req, res, next) => {
    Promise.resolve(fn(req, res, next))
      .catch(next);
  };

const invokeLambda = async (params) => {
  const data = await lambda.invoke(params).promise();
  return JSON.parse(data.Payload);
}


router.get('/test', asyncMiddleware(async (req, res, next) => {
  const params = {
    FunctionName: SOMETHING_LAMBDA_ARN,
    Payload: JSON.stringify(req.body)
  };
  const result = await invokeLambda(params);
  res.send(result);
}));

2
MiaeKim

Je voulais une solution similaire à celle ci-dessus. Bien que les fonctions d'étape soient désormais recommandées lors de l'utilisation de plusieurs fonctions lambda sur lambda.invoke, J'ai utilisé l'extrait de code suivant pour appeler de manière asynchrone deux autres fonctions lambda à partir de ma fonction lambda de base.

var AWS = require('aws-sdk');
AWS.config.region = 'ap-southeast-1';
var lambda = new AWS.Lambda();

exports.handler = async(event) => {
   await invokeLambda(event);

   const response = {
        statusCode: 200,
        body: JSON.stringify('success'),
   };

   return response;
};

//Invoke Multiple Lambda functions
  async function invokeLambda(event) {
    const function1 = {
        FunctionName: 'dev-test-async-lambda-1',
        InvocationType: 'Event',
        Payload: JSON.stringify(event)
    };

    const function2 = {
        FunctionName: 'dev-test-async-lambda-2',
        InvocationType: 'Event',
        Payload: JSON.stringify(event)
    };

    await lambda.invoke(function1).promise();
    await lambda.invoke(function2).promise();

}

Faites-moi savoir si je peux améliorer cela pour plus d'efficacité ou si vous le trouvez utile.

0
Cnf271