web-dev-qa-db-fra.com

Une fonction AWS Lambda peut-elle en appeler une autre

J'ai 2 fonctions Lambda - une qui produit un devis et l'autre qui transforme un devis en ordre ... Je voudrais que la fonction Ordre lambda appelle la fonction Quote pour régénérer le devis plutôt que de le recevoir simplement d'un fournisseur non approuvé. client.

J'ai regardé partout où je pouvais penser - mais je ne vois pas comment je pourrais enchaîner ou appeler les fonctions ... ça existe sûrement!

206
Silver

J'ai trouvé un moyen d'utiliser le aws-sdk.

var aws = require('aws-sdk');
var lambda = new aws.Lambda({
  region: 'us-west-2' //change to your region
});

lambda.invoke({
  FunctionName: 'name_of_your_lambda_function',
  Payload: JSON.stringify(event, null, 2) // pass params
}, function(error, data) {
  if (error) {
    context.done('error', error);
  }
  if(data.Payload){
   context.succeed(data.Payload)
  }
});

Vous trouverez la doc ici: http://docs.aws.Amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html

267
Nicolas Grenié

Vous devriez chaîner votre Lambda functions via SNS. Cette approche offre de bonnes performances, latence et évolutivité pour un effort minimal.

Votre première Lambda publie des messages dans votre SNS Topic et la seconde Lambda est abonnée à cette rubrique. Dès que les messages arrivent dans la rubrique, la seconde Lambda est exécutée avec le message en tant que paramètre d'entrée.

Voir Invocation de fonctions Lambda à l'aide de notifications Amazon SNS .

Vous pouvez également utiliser cette approche pour Invoquer des fonctions Lambda entre comptes via SNS .

81
kixorz

voici un exemple de code pour python,

from boto3 import client as boto3_client
from datetime import datetime
import json

lambda_client = boto3_client('lambda')

def lambda_handler(event, context):
    msg = {"key":"new_invocation", "at": datetime.now()}
    invoke_response = lambda_client.invoke(FunctionName="another_lambda_",
                                           InvocationType='Event',
                                           Payload=json.dumps(msg))
    print(invoke_response)

Btw, vous auriez besoin d'ajouter une politique comme celle-ci à votre rôle de lambda

   {
        "Sid": "Stmt1234567890",
        "Effect": "Allow",
        "Action": [
            "lambda:InvokeFunction"
        ],
        "Resource": "*"
    }
46
blueskin

Depuis que cette question a été posée, Amazon a publié Step Functions ( https://aws.Amazon.com/step-functions/ ). 

L'un des principes fondamentaux de AWS Lambda est que vous pouvez vous concentrer davantage sur la logique métier et moins sur la logique d'application qui les relie. Fonctions pas à pas vous permet d'orchestrer des interactions complexes entre les fonctions sans avoir à écrire le code pour le faire.

20
dustinnoe

Je cherchais à supprimer SNS jusqu'à ce que je voie cela dans la documentation client Lambda (version Java) :

Client pour accéder à AWS Lambda. Tous les appels de service passés à l'aide de ce client sont bloquants et ne seront renvoyés qu'une fois l'appel de service terminé.

SNS a donc un avantage évident: il est asynchrone. Votre lambda n'attendra pas que le lambda suivant soit terminé.

9
Ben Iggulden

Je travaillais avec la réponse fournie par blueskin mais je ne pouvais pas lire la réponse de Payload car le InvocationType = 'Event' est async , alors j’ai changé en InvocationType = 'RequestResponse' et maintenant. tout fonctionne bien.

4
antonio

Amazon a introduit les fonctions d'étapes dans AWS lambda en 2016. Je pense qu'il est maintenant plus pratique d'utiliser les fonctions d'étapes, car elles sont vraiment faciles à utiliser. Vous pouvez construire une machine à états avec deux fonctions lambda comme:

  • produire un devis
  • transforme un devis en commande

Vous pouvez facilement le faire comme ci-dessous: 

Ici vous pouvez avoir le premier état pour produit un devis et un autre pour passer à l'ordre

{
  Comment: "Produce a quote and turns into an order",
  StartAt: "ProduceQuote",
  States: {
    ProduceQuote: {
      "Type": Task,
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:ProduceQuote",
      "next": TurnsToOrder
    }
    TurnsToOrder: {
      Type: Task,
      Resource: "arn:aws:lambda:us-east-1:123456789012:function:ProduceQuote",
      end: true
    }
  }
}

Les fonctions Steps facilitent l'écriture de plusieurs fonctions lambda et leur exécution séquentielle ou parallèle . Vous pouvez obtenir plus d'informations sur les fonctions des étapes lambda ici: Steps Fonctions

3
Sunil Kapil

En Java, on peut faire comme suit:

AWSLambdaAsync awsLambdaAsync = AWSLambdaAsyncClientBuilder.standard().withRegion("us-east-1").build();

InvokeRequest invokeRequest = new InvokeRequest();
invokeRequest.withFunctionName("youLambdaFunctionNameToCall").withPayload(payload);

InvokeResult invokeResult = awsLambdaAsync.invoke(invokeRequest); 

Ici, payload est votre objet stringified Java qui doit être transmis en tant qu'objet Json à un autre lambda au cas où vous auriez besoin de transmettre certaines informations de l'appelant lambda à lambda.

2
Suyash

Vous pourrez peut-être utiliser la fonctionnalité Cascade Async.js - voir la partie inférieure du gros bloc de code à l'étape 3 de ce document pour obtenir un exemple: 

https://aws.Amazon.com/blogs/compute/better-together-Amazon-ecs-and-aws-lambda/

2
Mike

Une sorte de solution détournée, mais j’appelle simplement le point de terminaison API pour mes fonctions lambda lorsque je dois les chaîner. Cela vous permet de décider lors du codage si vous voulez qu’ils soient asynchrones ou non.

Si vous ne souhaitez pas configurer une requête POST, vous pouvez simplement configurer une requête GET simple avec quelques paramètres de chaîne de requête, voire aucun, pour faciliter la transmission d'événements. 

-- Modifier --

Voir: https://docs.aws.Amazon.com/apigateway/api-reference/making-http-requests/

et: http://docs.aws.Amazon.com/lambda/latest/dg/with-on-demand-https-example.html

1
Anselm

Vous pouvez appeler directement la fonction lambda (au moins via Java) en utilisant AWSLambdaClient comme décrit dans le blog post du blog AWS. 

1
Neil

Cette solution utilise boto3 et python:

import boto3
import json

invokeLambda = boto3.client('lambda', region_name='eu-west-1')

def lambda_handler(event, context):
    invokeLambda.invoke(FunctionName = 'function_name', InvocationType = 'RequestResponse', Payload = json.dumps(event))

    return True
1
Trilok Nagvenkar

Je rencontre le même problème, mais la fonction Lambda implémentée insère une entrée dans DynamoDB. Par conséquent, ma solution utilise des déclencheurs DynamoDB.

Je fais en sorte que la base de données appelle une fonction Lambda pour chaque insertion/mise à jour de la table, afin de séparer l'implémentation de deux fonctions Lambda.

La documentation est ici: http://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/Streams.Lambda.html

Voici une procédure guidée: https://aws.Amazon.com/blogs/aws/dynamodb-update-triggers-streams-lambda-cross-region-replication-app/

1
Lewen

Vous pouvez définir l'environnement AWS_REGION.

assert(process.env.AWS_REGION, 'Missing AWS_REGION env (eg. ap-northeast-1)');
const aws = require('aws-sdk');
const lambda = new aws.Lambda();
0
hojin